diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-22 17:01:44 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-22 17:01:44 -0700 |
commit | f9035cd498486d5a82ad8ae9bcfdb91b3e57ec9d (patch) | |
tree | f90d0fc8abc1edf7fd161252704bb5675f3460d0 | |
parent | 1821f7cd65ad9ea56580b830ac79bf4c4fef59cb (diff) | |
parent | 41bf37117b47fc5ce2aae91f6a108e7e42e0b046 (diff) | |
download | op-kernel-dev-f9035cd498486d5a82ad8ae9bcfdb91b3e57ec9d.zip op-kernel-dev-f9035cd498486d5a82ad8ae9bcfdb91b3e57ec9d.tar.gz |
Merge branch 'for-davem' of ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
177 files changed, 7151 insertions, 6085 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 41ec646..a116b35 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4097,6 +4097,12 @@ S: Maintained F: drivers/net/mv643xx_eth.* F: include/linux/mv643xx.h +MARVELL MWIFIEX WIRELESS DRIVER +M: Bing Zhao <bzhao@marvell.com> +L: linux-wireless@vger.kernel.org +S: Maintained +F: drivers/net/wireless/mwifiex/ + MARVELL MWL8K WIRELESS DRIVER M: Lennert Buytenhek <buytenh@wantstofly.org> L: linux-wireless@vger.kernel.org @@ -6948,9 +6954,9 @@ S: Maintained F: drivers/input/misc/wistron_btns.c WL1251 WIRELESS DRIVER -M: Kalle Valo <kvalo@adurom.com> +M: Luciano Coelho <coelho@ti.com> L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org +W: http://wireless.kernel.org/en/users/Drivers/wl1251 T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained F: drivers/net/wireless/wl1251/* diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 1ec7d45..4a04a49 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c @@ -50,3 +50,75 @@ int bcma_core_enable(struct bcma_device *core, u32 flags) return 0; } EXPORT_SYMBOL_GPL(bcma_core_enable); + +void bcma_core_set_clockmode(struct bcma_device *core, + enum bcma_clkmode clkmode) +{ + u16 i; + + WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON && + core->id.id != BCMA_CORE_PCIE && + core->id.id != BCMA_CORE_80211); + + switch (clkmode) { + case BCMA_CLKMODE_FAST: + bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); + udelay(64); + for (i = 0; i < 1500; i++) { + if (bcma_read32(core, BCMA_CLKCTLST) & + BCMA_CLKCTLST_HAVEHT) { + i = 0; + break; + } + udelay(10); + } + if (i) + pr_err("HT force timeout\n"); + break; + case BCMA_CLKMODE_DYNAMIC: + pr_warn("Dynamic clockmode not supported yet!\n"); + break; + } +} +EXPORT_SYMBOL_GPL(bcma_core_set_clockmode); + +void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) +{ + u16 i; + + WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ); + WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST); + + if (on) { + bcma_set32(core, BCMA_CLKCTLST, req); + for (i = 0; i < 10000; i++) { + if ((bcma_read32(core, BCMA_CLKCTLST) & status) == + status) { + i = 0; + break; + } + udelay(10); + } + if (i) + pr_err("PLL enable timeout\n"); + } else { + pr_warn("Disabling PLL not supported yet!\n"); + } +} +EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); + +u32 bcma_core_dma_translation(struct bcma_device *core) +{ + switch (core->bus->hosttype) { + case BCMA_HOSTTYPE_PCI: + if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) + return BCMA_DMA_TRANSLATION_DMA64_CMT; + else + return BCMA_DMA_TRANSLATION_DMA32_CMT; + default: + pr_err("DMA translation unknown for host %d\n", + core->bus->hosttype); + } + return BCMA_DMA_TRANSLATION_NONE; +} +EXPORT_SYMBOL(bcma_core_dma_translation); diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 6061022..fb54302 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) { + u32 leddc_on = 10; + u32 leddc_off = 90; + if (cc->core->id.rev >= 11) cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); @@ -38,6 +41,17 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) bcma_pmu_init(cc); if (cc->capabilities & BCMA_CC_CAP_PCTL) pr_err("Power control not implemented!\n"); + + if (cc->core->id.rev >= 16) { + if (cc->core->bus->sprom.leddc_on_time && + cc->core->bus->sprom.leddc_off_time) { + leddc_on = cc->core->bus->sprom.leddc_on_time; + leddc_off = cc->core->bus->sprom.leddc_off_time; + } + bcma_cc_write32(cc, BCMA_CC_GPIOTIMER, + ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | + (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); + } } /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index dc6f34a..745d264 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -172,8 +172,10 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) chipid_top != 0x5300) return false; +#ifdef CONFIG_SSB_DRIVER_PCICORE if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) return false; +#endif /* CONFIG_SSB_DRIVER_PCICORE */ #if 0 /* TODO: on BCMA we use address from EROM instead of magic formula */ diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 8e8d5cf..8b5b785 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -20,12 +20,12 @@ * R/W ops. **************************************************/ -static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom) +static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom) { int i; for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++) sprom[i] = bcma_read16(bus->drv_cc.core, - BCMA_CC_SPROM + (i * 2)); + offset + (i * 2)); } /************************************************** @@ -112,7 +112,7 @@ static int bcma_sprom_valid(const u16 *sprom) return err; revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; - if (revision != 8) { + if (revision != 8 && revision != 9) { pr_err("Unsupported SPROM revision: %d\n", revision); return -ENOENT; } @@ -137,6 +137,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) int bcma_sprom_get(struct bcma_bus *bus) { + u16 offset; u16 *sprom; int err = 0; @@ -151,7 +152,12 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - bcma_sprom_read(bus, sprom); + /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). + * According to brcm80211 this applies to cards with PCIe rev >= 6 + * TODO: understand this condition and use it */ + offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM : + BCMA_CC_SPROM_PCIE6; + bcma_sprom_read(bus, offset, sprom); err = bcma_sprom_valid(sprom); if (err) diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index ba682a0..9f69a4c 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -35,8 +35,8 @@ static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz) static bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) { - struct ath5k_softc *sc = common->priv; - struct platform_device *pdev = to_platform_device(sc->dev); + struct ath5k_hw *ah = common->priv; + struct platform_device *pdev = to_platform_device(ah->dev); struct ar231x_board_config *bcfg = pdev->dev.platform_data; u16 *eeprom, *eeprom_end; @@ -56,8 +56,7 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) int ath5k_hw_read_srev(struct ath5k_hw *ah) { - struct ath5k_softc *sc = ah->ah_sc; - struct platform_device *pdev = to_platform_device(sc->dev); + struct platform_device *pdev = to_platform_device(ah->dev); struct ar231x_board_config *bcfg = pdev->dev.platform_data; ah->ah_mac_srev = bcfg->devid; return 0; @@ -65,12 +64,11 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) { - struct ath5k_softc *sc = ah->ah_sc; - struct platform_device *pdev = to_platform_device(sc->dev); + struct platform_device *pdev = to_platform_device(ah->dev); struct ar231x_board_config *bcfg = pdev->dev.platform_data; u8 *cfg_mac; - if (to_platform_device(sc->dev)->id == 0) + if (to_platform_device(ah->dev)->id == 0) cfg_mac = bcfg->config->wlan0_mac; else cfg_mac = bcfg->config->wlan1_mac; @@ -90,7 +88,7 @@ static const struct ath_bus_ops ath_ahb_bus_ops = { static int ath_ahb_probe(struct platform_device *pdev) { struct ar231x_board_config *bcfg = pdev->dev.platform_data; - struct ath5k_softc *sc; + struct ath5k_hw *ah; struct ieee80211_hw *hw; struct resource *res; void __iomem *mem; @@ -127,19 +125,19 @@ static int ath_ahb_probe(struct platform_device *pdev) irq = res->start; - hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops); + hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops); if (hw == NULL) { dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); ret = -ENOMEM; goto err_out; } - sc = hw->priv; - sc->hw = hw; - sc->dev = &pdev->dev; - sc->iobase = mem; - sc->irq = irq; - sc->devid = bcfg->devid; + ah = hw->priv; + ah->hw = hw; + ah->dev = &pdev->dev; + ah->iobase = mem; + ah->irq = irq; + ah->devid = bcfg->devid; if (bcfg->devid >= AR5K_SREV_AR2315_R6) { /* Enable WMAC AHB arbitration */ @@ -155,7 +153,7 @@ static int ath_ahb_probe(struct platform_device *pdev) /* Enable WMAC DMA access (assuming 5312 or 231x*/ /* TODO: check other platforms */ reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); - if (to_platform_device(sc->dev)->id == 0) + if (to_platform_device(ah->dev)->id == 0) reg |= AR5K_AR5312_ENABLE_WLAN0; else reg |= AR5K_AR5312_ENABLE_WLAN1; @@ -166,13 +164,13 @@ static int ath_ahb_probe(struct platform_device *pdev) * used as pass-through. Disable 2 GHz support in the * driver for it */ - if (to_platform_device(sc->dev)->id == 0 && + if (to_platform_device(ah->dev)->id == 0 && (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) == (BD_WLAN1 | BD_WLAN0)) - __set_bit(ATH_STAT_2G_DISABLED, sc->status); + __set_bit(ATH_STAT_2G_DISABLED, ah->status); } - ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); + ret = ath5k_init_softc(ah, &ath_ahb_bus_ops); if (ret != 0) { dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); ret = -ENODEV; @@ -194,13 +192,13 @@ static int ath_ahb_remove(struct platform_device *pdev) { struct ar231x_board_config *bcfg = pdev->dev.platform_data; struct ieee80211_hw *hw = platform_get_drvdata(pdev); - struct ath5k_softc *sc; + struct ath5k_hw *ah; u32 reg; if (!hw) return 0; - sc = hw->priv; + ah = hw->priv; if (bcfg->devid >= AR5K_SREV_AR2315_R6) { /* Disable WMAC AHB arbitration */ @@ -210,14 +208,14 @@ static int ath_ahb_remove(struct platform_device *pdev) } else { /*Stop DMA access */ reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); - if (to_platform_device(sc->dev)->id == 0) + if (to_platform_device(ah->dev)->id == 0) reg &= ~AR5K_AR5312_ENABLE_WLAN0; else reg &= ~AR5K_AR5312_ENABLE_WLAN1; __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); } - ath5k_deinit_softc(sc); + ath5k_deinit_softc(ah); platform_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 2f0b967..603ae15 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -74,7 +74,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) static const s8 fr[] = { -78, -80 }; #endif if (level < 0 || level >= ARRAY_SIZE(sz)) { - ATH5K_ERR(ah->ah_sc, "noise immunity level %d out of range", + ATH5K_ERR(ah, "noise immunity level %d out of range", level); return; } @@ -88,8 +88,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRPWR, fr[level]); - ah->ah_sc->ani_state.noise_imm_level = level; - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); + ah->ani_state.noise_imm_level = level; + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); } @@ -105,8 +105,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; if (level < 0 || level >= ARRAY_SIZE(val) || - level > ah->ah_sc->ani_state.max_spur_level) { - ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range", + level > ah->ani_state.max_spur_level) { + ATH5K_ERR(ah, "spur immunity level %d out of range", level); return; } @@ -114,8 +114,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]); - ah->ah_sc->ani_state.spur_level = level; - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); + ah->ani_state.spur_level = level; + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); } @@ -130,15 +130,15 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) static const int val[] = { 0, 4, 8 }; if (level < 0 || level >= ARRAY_SIZE(val)) { - ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); + ATH5K_ERR(ah, "firstep level %d out of range", level); return; } AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRSTEP, val[level]); - ah->ah_sc->ani_state.firstep_level = level; - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); + ah->ani_state.firstep_level = level; + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); } @@ -178,8 +178,8 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); - ah->ah_sc->ani_state.ofdm_weak_sig = on; - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", + ah->ani_state.ofdm_weak_sig = on; + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s", on ? "on" : "off"); } @@ -195,8 +195,8 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) static const int val[] = { 8, 6 }; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); - ah->ah_sc->ani_state.cck_weak_sig = on; - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", + ah->ani_state.cck_weak_sig = on; + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s", on ? "on" : "off"); } @@ -218,7 +218,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, { int rssi = ewma_read(&ah->ah_beacon_rssi_avg); - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "raise immunity (%s)", ofdm_trigger ? "ODFM" : "CCK"); /* first: raise noise immunity */ @@ -229,13 +229,13 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, /* only OFDM: raise spur immunity level */ if (ofdm_trigger && - as->spur_level < ah->ah_sc->ani_state.max_spur_level) { + as->spur_level < ah->ani_state.max_spur_level) { ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1); return; } /* AP mode */ - if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { + if (ah->opmode == NL80211_IFTYPE_AP) { if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); return; @@ -248,7 +248,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, * don't shut out a remote node by raising immunity too high. */ if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "beacon RSSI high"); /* only OFDM: beacon RSSI is high, we can disable ODFM weak * signal detection */ @@ -265,7 +265,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { /* beacon RSSI in mid range, we need OFDM weak signal detect, * but can raise firstep level */ - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "beacon RSSI mid"); if (ofdm_trigger && as->ofdm_weak_sig == false) ath5k_ani_set_ofdm_weak_signal_detection(ah, true); @@ -275,7 +275,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, } else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) { /* beacon RSSI is low. in B/G mode turn of OFDM weak signal * detect and zero firstep level to maximize CCK sensitivity */ - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "beacon RSSI low, 2GHz"); if (ofdm_trigger && as->ofdm_weak_sig == true) ath5k_ani_set_ofdm_weak_signal_detection(ah, false); @@ -303,9 +303,9 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) { int rssi = ewma_read(&ah->ah_beacon_rssi_avg); - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "lower immunity"); - if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { + if (ah->opmode == NL80211_IFTYPE_AP) { /* AP mode */ if (as->firstep_level > 0) { ath5k_ani_set_firstep_level(ah, as->firstep_level - 1); @@ -464,7 +464,7 @@ ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) void ath5k_ani_calibration(struct ath5k_hw *ah) { - struct ath5k_ani_state *as = &ah->ah_sc->ani_state; + struct ath5k_ani_state *as = &ah->ani_state; int listen, ofdm_high, ofdm_low, cck_high, cck_low; /* get listen time since last call and add it to the counter because we @@ -483,9 +483,9 @@ ath5k_ani_calibration(struct ath5k_hw *ah) ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000; cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000; - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "listen %d (now %d)", as->listen_time, listen); - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "check high ofdm %d/%d cck %d/%d", as->ofdm_errors, ofdm_high, as->cck_errors, cck_high); @@ -498,7 +498,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah) } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { /* If more than 5 (TODO: why 5?) periods have passed and we got * relatively little errors we can try to lower immunity */ - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "check low ofdm %d/%d cck %d/%d", as->ofdm_errors, ofdm_low, as->cck_errors, cck_low); @@ -525,7 +525,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah) void ath5k_ani_mib_intr(struct ath5k_hw *ah) { - struct ath5k_ani_state *as = &ah->ah_sc->ani_state; + struct ath5k_ani_state *as = &ah->ani_state; /* nothing to do here if HW does not have PHY error counters - they * can't be the reason for the MIB interrupt then */ @@ -536,7 +536,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); - if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) + if (ah->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) return; /* If one of the errors triggered, we can get a superfluous second @@ -547,7 +547,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH || as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) - tasklet_schedule(&ah->ah_sc->ani_tasklet); + tasklet_schedule(&ah->ani_tasklet); } @@ -561,16 +561,16 @@ void ath5k_ani_phy_error_report(struct ath5k_hw *ah, enum ath5k_phy_error_code phyerr) { - struct ath5k_ani_state *as = &ah->ah_sc->ani_state; + struct ath5k_ani_state *as = &ah->ani_state; if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) { as->ofdm_errors++; if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH) - tasklet_schedule(&ah->ah_sc->ani_tasklet); + tasklet_schedule(&ah->ani_tasklet); } else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) { as->cck_errors++; if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) - tasklet_schedule(&ah->ah_sc->ani_tasklet); + tasklet_schedule(&ah->ani_tasklet); } } @@ -631,24 +631,24 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) return; if (mode < ATH5K_ANI_MODE_OFF || mode > ATH5K_ANI_MODE_AUTO) { - ATH5K_ERR(ah->ah_sc, "ANI mode %d out of range", mode); + ATH5K_ERR(ah, "ANI mode %d out of range", mode); return; } /* clear old state information */ - memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state)); + memset(&ah->ani_state, 0, sizeof(ah->ani_state)); /* older hardware has more spur levels than newer */ if (ah->ah_mac_srev < AR5K_SREV_AR2414) - ah->ah_sc->ani_state.max_spur_level = 7; + ah->ani_state.max_spur_level = 7; else - ah->ah_sc->ani_state.max_spur_level = 2; + ah->ani_state.max_spur_level = 2; /* initial values for our ani parameters */ if (mode == ATH5K_ANI_MODE_OFF) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n"); + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI off\n"); } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI manual low -> high sensitivity\n"); ath5k_ani_set_noise_immunity_level(ah, 0); ath5k_ani_set_spur_immunity_level(ah, 0); @@ -656,17 +656,17 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) ath5k_ani_set_ofdm_weak_signal_detection(ah, true); ath5k_ani_set_cck_weak_signal_detection(ah, true); } else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI manual high -> low sensitivity\n"); ath5k_ani_set_noise_immunity_level(ah, ATH5K_ANI_MAX_NOISE_IMM_LVL); ath5k_ani_set_spur_immunity_level(ah, - ah->ah_sc->ani_state.max_spur_level); + ah->ani_state.max_spur_level); ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); ath5k_ani_set_ofdm_weak_signal_detection(ah, false); ath5k_ani_set_cck_weak_signal_detection(ah, false); } else if (mode == ATH5K_ANI_MODE_AUTO) { - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n"); + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI auto\n"); ath5k_ani_set_noise_immunity_level(ah, 0); ath5k_ani_set_spur_immunity_level(ah, 0); ath5k_ani_set_firstep_level(ah, 0); @@ -692,7 +692,7 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) ~AR5K_RX_FILTER_PHYERR); } - ah->ah_sc->ani_state.ani_mode = mode; + ah->ani_state.ani_mode = mode; } diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 8ff1794..277d5cb 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -24,8 +24,10 @@ #define CHAN_DEBUG 0 #include <linux/io.h> +#include <linux/interrupt.h> #include <linux/types.h> #include <linux/average.h> +#include <linux/leds.h> #include <net/mac80211.h> /* RX/TX descriptor hw structs @@ -36,7 +38,9 @@ * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) * and clean up common bits, then introduce set/get functions in eeprom.c */ #include "eeprom.h" +#include "debug.h" #include "../ath.h" +#include "ani.h" /* PCI IDs */ #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ @@ -538,6 +542,27 @@ enum ath5k_tx_queue_id { #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ /* + * Data transmit queue state. One of these exists for each + * hardware transmit queue. Packets sent to us from above + * are assigned to queues based on their priority. Not all + * devices support a complete set of hardware transmit queues. + * For those devices the array sc_ac2q will map multiple + * priorities to fewer hardware queues (typically all to one + * hardware queue). + */ +struct ath5k_txq { + unsigned int qnum; /* hardware q number */ + u32 *link; /* link ptr in last TX desc */ + struct list_head q; /* transmit queue */ + spinlock_t lock; /* lock on q and link */ + bool setup; + int txq_len; /* number of queued buffers */ + int txq_max; /* max allowed num of queued buffers */ + bool txq_poll_mark; + unsigned int txq_stuck; /* informational counter */ +}; + +/* * A struct to hold tx queue's parameters */ struct ath5k_txq_info { @@ -947,35 +972,6 @@ enum ath5k_power_mode { #define AR5K_SOFTLED_ON 0 #define AR5K_SOFTLED_OFF 1 -/* - * Chipset capabilities -see ath5k_hw_get_capability- - * get_capability function is not yet fully implemented - * in ath5k so most of these don't work yet... - * TODO: Implement these & merge with _TUNE_ stuff above - */ -enum ath5k_capability_type { - AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ - AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */ - AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */ - AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */ - AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */ - AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */ - AR5K_CAP_VEOL = 7, /* Supports virtual EOL */ - AR5K_CAP_COMPRESSION = 8, /* Supports compression */ - AR5K_CAP_BURST = 9, /* Supports packet bursting */ - AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */ - AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */ - AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */ - AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */ - AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */ - AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */ - AR5K_CAP_XR = 16, /* Supports XR mode */ - AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */ - AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */ - AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */ - AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */ -}; - /* XXX: we *may* move cap_range stuff to struct wiphy */ struct ath5k_capabilities { @@ -1027,9 +1023,66 @@ struct ath5k_avg_val { int avg_weight; }; -/***************************************\ - HARDWARE ABSTRACTION LAYER STRUCTURE -\***************************************/ +#define ATH5K_LED_MAX_NAME_LEN 31 + +/* + * State for LED triggers + */ +struct ath5k_led { + char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ + struct ath5k_hw *ah; /* driver state */ + struct led_classdev led_dev; /* led classdev */ +}; + +/* Rfkill */ +struct ath5k_rfkill { + /* GPIO PIN for rfkill */ + u16 gpio; + /* polarity of rfkill GPIO PIN */ + bool polarity; + /* RFKILL toggle tasklet */ + struct tasklet_struct toggleq; +}; + +/* statistics */ +struct ath5k_statistics { + /* antenna use */ + unsigned int antenna_rx[5]; /* frames count per antenna RX */ + unsigned int antenna_tx[5]; /* frames count per antenna TX */ + + /* frame errors */ + unsigned int rx_all_count; /* all RX frames, including errors */ + unsigned int tx_all_count; /* all TX frames, including errors */ + unsigned int rx_bytes_count; /* all RX bytes, including errored pkts + * and the MAC headers for each packet + */ + unsigned int tx_bytes_count; /* all TX bytes, including errored pkts + * and the MAC headers and padding for + * each packet. + */ + unsigned int rxerr_crc; + unsigned int rxerr_phy; + unsigned int rxerr_phy_code[32]; + unsigned int rxerr_fifo; + unsigned int rxerr_decrypt; + unsigned int rxerr_mic; + unsigned int rxerr_proc; + unsigned int rxerr_jumbo; + unsigned int txerr_retry; + unsigned int txerr_fifo; + unsigned int txerr_filt; + + /* MIB counters */ + unsigned int ack_fail; + unsigned int rts_fail; + unsigned int rts_ok; + unsigned int fcs_error; + unsigned int beacons; + + unsigned int mib_intr; + unsigned int rxorn_intr; + unsigned int rxeol_intr; +}; /* * Misc defines @@ -1038,12 +1091,114 @@ struct ath5k_avg_val { #define AR5K_MAX_GPIO 10 #define AR5K_MAX_RF_BANKS 8 -/* TODO: Clean up and merge with ath5k_softc */ +#if CHAN_DEBUG +#define ATH_CHAN_MAX (26 + 26 + 26 + 200 + 200) +#else +#define ATH_CHAN_MAX (14 + 14 + 14 + 252 + 20) +#endif + +#define ATH_RXBUF 40 /* number of RX buffers */ +#define ATH_TXBUF 200 /* number of TX buffers */ +#define ATH_BCBUF 4 /* number of beacon buffers */ +#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ +#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ + +/* Driver state associated with an instance of a device */ struct ath5k_hw { struct ath_common common; - struct ath5k_softc *ah_sc; - void __iomem *ah_iobase; + struct pci_dev *pdev; + struct device *dev; /* for dma mapping */ + int irq; + u16 devid; + void __iomem *iobase; /* address of the device */ + struct mutex lock; /* dev-level lock */ + struct ieee80211_hw *hw; /* IEEE 802.11 common */ + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ieee80211_channel channels[ATH_CHAN_MAX]; + struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; + s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; + enum nl80211_iftype opmode; + +#ifdef CONFIG_ATH5K_DEBUG + struct ath5k_dbg_info debug; /* debug info */ +#endif /* CONFIG_ATH5K_DEBUG */ + + struct ath5k_buf *bufptr; /* allocated buffer ptr */ + struct ath5k_desc *desc; /* TX/RX descriptors */ + dma_addr_t desc_daddr; /* DMA (physical) address */ + size_t desc_len; /* size of TX/RX descriptors */ + + DECLARE_BITMAP(status, 6); +#define ATH_STAT_INVALID 0 /* disable hardware accesses */ +#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ +#define ATH_STAT_PROMISC 2 +#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ +#define ATH_STAT_STARTED 4 /* opened & irqs enabled */ +#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ + + unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ + struct ieee80211_channel *curchan; /* current h/w channel */ + + u16 nvifs; + + enum ath5k_int imask; /* interrupt mask copy */ + + spinlock_t irqlock; + bool rx_pending; /* rx tasklet pending */ + bool tx_pending; /* tx tasklet pending */ + + u8 lladdr[ETH_ALEN]; + u8 bssidmask[ETH_ALEN]; + + unsigned int led_pin, /* GPIO pin for driving LED */ + led_on; /* pin setting for LED on */ + + struct work_struct reset_work; /* deferred chip reset */ + + unsigned int rxbufsize; /* rx size based on mtu */ + struct list_head rxbuf; /* receive buffer */ + spinlock_t rxbuflock; + u32 *rxlink; /* link ptr in last RX desc */ + struct tasklet_struct rxtq; /* rx intr tasklet */ + struct ath5k_led rx_led; /* rx led */ + + struct list_head txbuf; /* transmit buffer */ + spinlock_t txbuflock; + unsigned int txbuf_len; /* buf count in txbuf list */ + struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ + struct tasklet_struct txtq; /* tx intr tasklet */ + struct ath5k_led tx_led; /* tx led */ + + struct ath5k_rfkill rf_kill; + + struct tasklet_struct calib; /* calibration tasklet */ + + spinlock_t block; /* protects beacon */ + struct tasklet_struct beacontq; /* beacon intr tasklet */ + struct list_head bcbuf; /* beacon buffer */ + struct ieee80211_vif *bslot[ATH_BCBUF]; + u16 num_ap_vifs; + u16 num_adhoc_vifs; + unsigned int bhalq, /* SW q for outgoing beacons */ + bmisscount, /* missed beacon transmits */ + bintval, /* beacon interval in TU */ + bsent; + unsigned int nexttbtt; /* next beacon time in TU */ + struct ath5k_txq *cabq; /* content after beacon */ + + int power_level; /* Requested tx power in dBm */ + bool assoc; /* associate state */ + bool enable_beacon; /* true if beacons are on */ + + struct ath5k_statistics stats; + + struct ath5k_ani_state ani_state; + struct tasklet_struct ani_tasklet; /* ANI calibration */ + + struct delayed_work tx_complete_work; + + struct survey_info survey; /* collected survey info */ enum ath5k_int ah_imr; @@ -1172,43 +1327,43 @@ struct ath_bus_ops { extern const struct ieee80211_ops ath5k_hw_ops; /* Initialization and detach functions */ -int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops); -void ath5k_deinit_softc(struct ath5k_softc *sc); -int ath5k_hw_init(struct ath5k_softc *sc); +int ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops); +void ath5k_deinit_softc(struct ath5k_hw *ah); +int ath5k_hw_init(struct ath5k_hw *ah); void ath5k_hw_deinit(struct ath5k_hw *ah); -int ath5k_sysfs_register(struct ath5k_softc *sc); -void ath5k_sysfs_unregister(struct ath5k_softc *sc); +int ath5k_sysfs_register(struct ath5k_hw *ah); +void ath5k_sysfs_unregister(struct ath5k_hw *ah); /* base.c */ struct ath5k_buf; struct ath5k_txq; void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable); -bool ath5k_any_vif_assoc(struct ath5k_softc *sc); +bool ath5k_any_vif_assoc(struct ath5k_hw *ah); void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath5k_txq *txq); -int ath5k_init_hw(struct ath5k_softc *sc); -int ath5k_stop_hw(struct ath5k_softc *sc); -void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif); -void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, +int ath5k_start(struct ieee80211_hw *hw); +void ath5k_stop(struct ieee80211_hw *hw); +void ath5k_mode_setup(struct ath5k_hw *ah, struct ieee80211_vif *vif); +void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah, struct ieee80211_vif *vif); -int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan); -void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); +int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan); +void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf); int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void ath5k_beacon_config(struct ath5k_softc *sc); -void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); -void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); +void ath5k_beacon_config(struct ath5k_hw *ah); +void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); +void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); /*Chip id helper functions */ const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); int ath5k_hw_read_srev(struct ath5k_hw *ah); /* LED functions */ -int ath5k_init_leds(struct ath5k_softc *sc); -void ath5k_led_enable(struct ath5k_softc *sc); -void ath5k_led_off(struct ath5k_softc *sc); -void ath5k_unregister_leds(struct ath5k_softc *sc); +int ath5k_init_leds(struct ath5k_hw *ah); +void ath5k_led_enable(struct ath5k_hw *ah); +void ath5k_led_off(struct ath5k_hw *ah); +void ath5k_unregister_leds(struct ath5k_hw *ah); /* Reset Functions */ @@ -1322,9 +1477,6 @@ void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); /* Misc functions TODO: Cleanup */ int ath5k_hw_set_capabilities(struct ath5k_hw *ah); -int ath5k_hw_get_capability(struct ath5k_hw *ah, - enum ath5k_capability_type cap_type, u32 capability, - u32 *result); int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); @@ -1384,7 +1536,7 @@ static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg) (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6))) return AR5K_AR2315_PCI_BASE + reg; - return ah->ah_iobase + reg; + return ah->iobase + reg; } static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) @@ -1401,12 +1553,12 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) { - return ioread32(ah->ah_iobase + reg); + return ioread32(ah->iobase + reg); } static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) { - iowrite32(val, ah->ah_iobase + reg); + iowrite32(val, ah->iobase + reg); } #endif diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 14dc52e..f8a6b380 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -59,7 +59,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah) cur_val = ath5k_hw_reg_read(ah, cur_reg); if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); + ATH5K_ERR(ah, "POST Failed !!!\n"); return -EAGAIN; } @@ -74,7 +74,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah) cur_val = ath5k_hw_reg_read(ah, cur_reg); if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); + ATH5K_ERR(ah, "POST Failed !!!\n"); return -EAGAIN; } @@ -95,19 +95,18 @@ static int ath5k_hw_post(struct ath5k_hw *ah) /** * ath5k_hw_init - Check if hw is supported and init the needed structs * - * @sc: The &struct ath5k_softc we got from the driver's init_softc function + * @ah: The &struct ath5k_hw we got from the driver's init_softc function * * Check if the device is supported, perform a POST and initialize the needed * structs. Returns -ENOMEM if we don't have memory for the needed structs, * -ENODEV if the device is not supported or prints an error msg if something * else went wrong. */ -int ath5k_hw_init(struct ath5k_softc *sc) +int ath5k_hw_init(struct ath5k_hw *ah) { static const u8 zero_mac[ETH_ALEN] = { }; - struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); - struct pci_dev *pdev = sc->pdev; + struct pci_dev *pdev = ah->pdev; struct ath5k_eeprom_info *ee; int ret; u32 srev; @@ -123,8 +122,8 @@ int ath5k_hw_init(struct ath5k_softc *sc) ah->ah_retry_long = AR5K_INIT_RETRY_LONG; ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; ah->ah_noise_floor = -95; /* until first NF calibration is run */ - sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; - ah->ah_current_channel = &sc->channels[0]; + ah->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; + ah->ah_current_channel = &ah->channels[0]; /* * Find the mac version @@ -237,7 +236,7 @@ int ath5k_hw_init(struct ath5k_softc *sc) ah->ah_single_chip = true; ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; } else { - ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); + ATH5K_ERR(ah, "Couldn't identify radio revision.\n"); ret = -ENODEV; goto err; } @@ -246,7 +245,7 @@ int ath5k_hw_init(struct ath5k_softc *sc) /* Return on unsupported chips (unsupported eeprom etc) */ if ((srev >= AR5K_SREV_AR5416) && (srev < AR5K_SREV_AR2425)) { - ATH5K_ERR(sc, "Device not yet supported.\n"); + ATH5K_ERR(ah, "Device not yet supported.\n"); ret = -ENODEV; goto err; } @@ -268,7 +267,7 @@ int ath5k_hw_init(struct ath5k_softc *sc) */ ret = ath5k_eeprom_init(ah); if (ret) { - ATH5K_ERR(sc, "unable to init EEPROM\n"); + ATH5K_ERR(ah, "unable to init EEPROM\n"); goto err; } @@ -309,17 +308,17 @@ int ath5k_hw_init(struct ath5k_softc *sc) /* Get misc capabilities */ ret = ath5k_hw_set_capabilities(ah); if (ret) { - ATH5K_ERR(sc, "unable to get device capabilities\n"); + ATH5K_ERR(ah, "unable to get device capabilities\n"); goto err; } - if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) { + if (test_bit(ATH_STAT_2G_DISABLED, ah->status)) { __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); } /* Crypto settings */ - common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? + common->keymax = (ah->ah_version == AR5K_AR5210 ? AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); if (srev >= AR5K_SREV_AR5212_V4 && @@ -339,7 +338,7 @@ int ath5k_hw_init(struct ath5k_softc *sc) /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); ath5k_hw_set_bssid(ah); - ath5k_hw_set_opmode(ah, sc->opmode); + ath5k_hw_set_opmode(ah, ah->opmode); ath5k_hw_rfgain_opt_init(ah); @@ -360,7 +359,7 @@ err: */ void ath5k_hw_deinit(struct ath5k_hw *ah) { - __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); + __set_bit(ATH_STAT_INVALID, ah->status); if (ah->ah_rf_banks != NULL) kfree(ah->ah_rf_banks); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index dce848f..f54dff4 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -86,7 +86,7 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); static int ath5k_init(struct ieee80211_hw *hw); -static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, +static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, bool skip_pcu); /* Known SREVs */ @@ -238,8 +238,8 @@ static const struct ath_ops ath5k_common_ops = { static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath5k_softc *sc = hw->priv; - struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah); + struct ath5k_hw *ah = hw->priv; + struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); return ath_reg_notifier_apply(wiphy, request, regulatory); } @@ -289,7 +289,7 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, band = IEEE80211_BAND_2GHZ; break; default: - ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); + ATH5K_WARN(ah, "bad mode, not copying channels\n"); return 0; } @@ -327,51 +327,50 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, } static void -ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b) +ath5k_setup_rate_idx(struct ath5k_hw *ah, struct ieee80211_supported_band *b) { u8 i; for (i = 0; i < AR5K_MAX_RATES; i++) - sc->rate_idx[b->band][i] = -1; + ah->rate_idx[b->band][i] = -1; for (i = 0; i < b->n_bitrates; i++) { - sc->rate_idx[b->band][b->bitrates[i].hw_value] = i; + ah->rate_idx[b->band][b->bitrates[i].hw_value] = i; if (b->bitrates[i].hw_value_short) - sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i; + ah->rate_idx[b->band][b->bitrates[i].hw_value_short] = i; } } static int ath5k_setup_bands(struct ieee80211_hw *hw) { - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ieee80211_supported_band *sband; int max_c, count_c = 0; int i; - BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS); - max_c = ARRAY_SIZE(sc->channels); + BUILD_BUG_ON(ARRAY_SIZE(ah->sbands) < IEEE80211_NUM_BANDS); + max_c = ARRAY_SIZE(ah->channels); /* 2GHz band */ - sband = &sc->sbands[IEEE80211_BAND_2GHZ]; + sband = &ah->sbands[IEEE80211_BAND_2GHZ]; sband->band = IEEE80211_BAND_2GHZ; - sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0]; + sband->bitrates = &ah->rates[IEEE80211_BAND_2GHZ][0]; - if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) { + if (test_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode)) { /* G mode */ memcpy(sband->bitrates, &ath5k_rates[0], sizeof(struct ieee80211_rate) * 12); sband->n_bitrates = 12; - sband->channels = sc->channels; + sband->channels = ah->channels; sband->n_channels = ath5k_setup_channels(ah, sband->channels, AR5K_MODE_11G, max_c); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; count_c = sband->n_channels; max_c -= count_c; - } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) { + } else if (test_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode)) { /* B mode */ memcpy(sband->bitrates, &ath5k_rates[0], sizeof(struct ieee80211_rate) * 4); @@ -390,7 +389,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) } } - sband->channels = sc->channels; + sband->channels = ah->channels; sband->n_channels = ath5k_setup_channels(ah, sband->channels, AR5K_MODE_11B, max_c); @@ -398,27 +397,27 @@ ath5k_setup_bands(struct ieee80211_hw *hw) count_c = sband->n_channels; max_c -= count_c; } - ath5k_setup_rate_idx(sc, sband); + ath5k_setup_rate_idx(ah, sband); /* 5GHz band, A mode */ - if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) { - sband = &sc->sbands[IEEE80211_BAND_5GHZ]; + if (test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) { + sband = &ah->sbands[IEEE80211_BAND_5GHZ]; sband->band = IEEE80211_BAND_5GHZ; - sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0]; + sband->bitrates = &ah->rates[IEEE80211_BAND_5GHZ][0]; memcpy(sband->bitrates, &ath5k_rates[4], sizeof(struct ieee80211_rate) * 8); sband->n_bitrates = 8; - sband->channels = &sc->channels[count_c]; + sband->channels = &ah->channels[count_c]; sband->n_channels = ath5k_setup_channels(ah, sband->channels, AR5K_MODE_11A, max_c); hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } - ath5k_setup_rate_idx(sc, sband); + ath5k_setup_rate_idx(ah, sband); - ath5k_debug_dump_bands(sc); + ath5k_debug_dump_bands(ah); return 0; } @@ -428,14 +427,14 @@ ath5k_setup_bands(struct ieee80211_hw *hw) * To accomplish this we must first cleanup any pending DMA, * then restart stuff after a la ath5k_init. * - * Called with sc->lock. + * Called with ah->lock. */ int -ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) +ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan) { - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "channel set, resetting (%u -> %u MHz)\n", - sc->curchan->center_freq, chan->center_freq); + ah->curchan->center_freq, chan->center_freq); /* * To switch channels clear any pending DMA operations; @@ -443,7 +442,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - return ath5k_reset(sc, chan, true); + return ath5k_reset(ah, chan, true); } void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) @@ -487,10 +486,10 @@ void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) } void -ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, +ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah, struct ieee80211_vif *vif) { - struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_common *common = ath5k_hw_common(ah); struct ath5k_vif_iter_data iter_data; u32 rfilt; @@ -509,24 +508,24 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, ath5k_vif_iter(&iter_data, vif->addr, vif); /* Get list of all active MAC addresses */ - ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, + ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter, &iter_data); - memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); + memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN); - sc->opmode = iter_data.opmode; - if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED) + ah->opmode = iter_data.opmode; + if (ah->opmode == NL80211_IFTYPE_UNSPECIFIED) /* Nothing active, default to station mode */ - sc->opmode = NL80211_IFTYPE_STATION; + ah->opmode = NL80211_IFTYPE_STATION; - ath5k_hw_set_opmode(sc->ah, sc->opmode); - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", - sc->opmode, ath_opmode_to_string(sc->opmode)); + ath5k_hw_set_opmode(ah, ah->opmode); + ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", + ah->opmode, ath_opmode_to_string(ah->opmode)); if (iter_data.need_set_hw_addr && iter_data.found_active) - ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); + ath5k_hw_set_lladdr(ah, iter_data.active_mac); - if (ath5k_hw_hasbssidmask(sc->ah)) - ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); + if (ath5k_hw_hasbssidmask(ah)) + ath5k_hw_set_bssid_mask(ah, ah->bssidmask); /* Set up RX Filter */ if (iter_data.n_stas > 1) { @@ -534,16 +533,16 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, * different APs, ARPs are not received (most of the time?) * Enabling PROMISC appears to fix that problem. */ - sc->filter_flags |= AR5K_RX_FILTER_PROM; + ah->filter_flags |= AR5K_RX_FILTER_PROM; } - rfilt = sc->filter_flags; - ath5k_hw_set_rx_filter(sc->ah, rfilt); - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); + rfilt = ah->filter_flags; + ath5k_hw_set_rx_filter(ah, rfilt); + ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); } static inline int -ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) +ath5k_hw_to_driver_rix(struct ath5k_hw *ah, int hw_rix) { int rix; @@ -552,7 +551,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) "hw_rix out of bounds: %x\n", hw_rix)) return 0; - rix = sc->rate_idx[sc->curchan->band][hw_rix]; + rix = ah->rate_idx[ah->curchan->band][hw_rix]; if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) rix = 0; @@ -564,9 +563,9 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) \***************/ static -struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) +struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_hw *ah, dma_addr_t *skb_addr) { - struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_common *common = ath5k_hw_common(ah); struct sk_buff *skb; /* @@ -578,17 +577,17 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) GFP_ATOMIC); if (!skb) { - ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", + ATH5K_ERR(ah, "can't alloc skbuff of size %u\n", common->rx_bufsize); return NULL; } - *skb_addr = dma_map_single(sc->dev, + *skb_addr = dma_map_single(ah->dev, skb->data, common->rx_bufsize, DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) { - ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); + if (unlikely(dma_mapping_error(ah->dev, *skb_addr))) { + ATH5K_ERR(ah, "%s: DMA mapping failed\n", __func__); dev_kfree_skb(skb); return NULL; } @@ -596,15 +595,14 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) } static int -ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) +ath5k_rxbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf) { - struct ath5k_hw *ah = sc->ah; struct sk_buff *skb = bf->skb; struct ath5k_desc *ds; int ret; if (!skb) { - skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); + skb = ath5k_rx_skb_alloc(ah, &bf->skbaddr); if (!skb) return -ENOMEM; bf->skb = skb; @@ -630,13 +628,13 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ds->ds_data = bf->skbaddr; ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); if (ret) { - ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__); + ATH5K_ERR(ah, "%s: could not setup RX desc\n", __func__); return ret; } - if (sc->rxlink != NULL) - *sc->rxlink = bf->daddr; - sc->rxlink = &ds->ds_link; + if (ah->rxlink != NULL) + *ah->rxlink = bf->daddr; + ah->rxlink = &ds->ds_link; return 0; } @@ -664,10 +662,9 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) } static int -ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, +ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, struct ath5k_txq *txq, int padsize) { - struct ath5k_hw *ah = sc->ah; struct ath5k_desc *ds = bf->desc; struct sk_buff *skb = bf->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -683,10 +680,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; /* XXX endianness */ - bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len, DMA_TO_DEVICE); - rate = ieee80211_get_tx_rate(sc->hw, info); + rate = ieee80211_get_tx_rate(ah->hw, info); if (!rate) { ret = -EINVAL; goto err_unmap; @@ -710,20 +707,20 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, } if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { flags |= AR5K_TXDESC_RTSENA; - cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; - duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, + cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value; + duration = le16_to_cpu(ieee80211_rts_duration(ah->hw, info->control.vif, pktlen, info)); } if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { flags |= AR5K_TXDESC_CTSENA; - cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; - duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, + cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value; + duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw, info->control.vif, pktlen, info)); } ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), padsize, get_hw_packet_type(skb), - (sc->power_level * 2), + (ah->power_level * 2), hw_rate, info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, cts_rate, duration); @@ -733,7 +730,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, memset(mrr_rate, 0, sizeof(mrr_rate)); memset(mrr_tries, 0, sizeof(mrr_tries)); for (i = 0; i < 3; i++) { - rate = ieee80211_get_alt_retry_rate(sc->hw, info, i); + rate = ieee80211_get_alt_retry_rate(ah->hw, info, i); if (!rate) break; @@ -764,7 +761,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, return 0; err_unmap: - dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); + dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@ -773,7 +770,7 @@ err_unmap: \*******************/ static int -ath5k_desc_alloc(struct ath5k_softc *sc) +ath5k_desc_alloc(struct ath5k_hw *ah) { struct ath5k_desc *ds; struct ath5k_buf *bf; @@ -782,68 +779,68 @@ ath5k_desc_alloc(struct ath5k_softc *sc) int ret; /* allocate descriptors */ - sc->desc_len = sizeof(struct ath5k_desc) * + ah->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); - sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len, - &sc->desc_daddr, GFP_KERNEL); - if (sc->desc == NULL) { - ATH5K_ERR(sc, "can't allocate descriptors\n"); + ah->desc = dma_alloc_coherent(ah->dev, ah->desc_len, + &ah->desc_daddr, GFP_KERNEL); + if (ah->desc == NULL) { + ATH5K_ERR(ah, "can't allocate descriptors\n"); ret = -ENOMEM; goto err; } - ds = sc->desc; - da = sc->desc_daddr; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n", - ds, sc->desc_len, (unsigned long long)sc->desc_daddr); + ds = ah->desc; + da = ah->desc_daddr; + ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n", + ds, ah->desc_len, (unsigned long long)ah->desc_daddr); bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF, sizeof(struct ath5k_buf), GFP_KERNEL); if (bf == NULL) { - ATH5K_ERR(sc, "can't allocate bufptr\n"); + ATH5K_ERR(ah, "can't allocate bufptr\n"); ret = -ENOMEM; goto err_free; } - sc->bufptr = bf; + ah->bufptr = bf; - INIT_LIST_HEAD(&sc->rxbuf); + INIT_LIST_HEAD(&ah->rxbuf); for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) { bf->desc = ds; bf->daddr = da; - list_add_tail(&bf->list, &sc->rxbuf); + list_add_tail(&bf->list, &ah->rxbuf); } - INIT_LIST_HEAD(&sc->txbuf); - sc->txbuf_len = ATH_TXBUF; + INIT_LIST_HEAD(&ah->txbuf); + ah->txbuf_len = ATH_TXBUF; for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) { bf->desc = ds; bf->daddr = da; - list_add_tail(&bf->list, &sc->txbuf); + list_add_tail(&bf->list, &ah->txbuf); } /* beacon buffers */ - INIT_LIST_HEAD(&sc->bcbuf); + INIT_LIST_HEAD(&ah->bcbuf); for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) { bf->desc = ds; bf->daddr = da; - list_add_tail(&bf->list, &sc->bcbuf); + list_add_tail(&bf->list, &ah->bcbuf); } return 0; err_free: - dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr); err: - sc->desc = NULL; + ah->desc = NULL; return ret; } void -ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) +ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf) { BUG_ON(!bf); if (!bf->skb) return; - dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len, + dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; @@ -852,15 +849,14 @@ ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) } void -ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) +ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf) { - struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); BUG_ON(!bf); if (!bf->skb) return; - dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, + dma_unmap_single(ah->dev, bf->skbaddr, common->rx_bufsize, DMA_FROM_DEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; @@ -869,24 +865,24 @@ ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) } static void -ath5k_desc_free(struct ath5k_softc *sc) +ath5k_desc_free(struct ath5k_hw *ah) { struct ath5k_buf *bf; - list_for_each_entry(bf, &sc->txbuf, list) - ath5k_txbuf_free_skb(sc, bf); - list_for_each_entry(bf, &sc->rxbuf, list) - ath5k_rxbuf_free_skb(sc, bf); - list_for_each_entry(bf, &sc->bcbuf, list) - ath5k_txbuf_free_skb(sc, bf); + list_for_each_entry(bf, &ah->txbuf, list) + ath5k_txbuf_free_skb(ah, bf); + list_for_each_entry(bf, &ah->rxbuf, list) + ath5k_rxbuf_free_skb(ah, bf); + list_for_each_entry(bf, &ah->bcbuf, list) + ath5k_txbuf_free_skb(ah, bf); /* Free memory associated with all descriptors */ - dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); - sc->desc = NULL; - sc->desc_daddr = 0; + dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr); + ah->desc = NULL; + ah->desc_daddr = 0; - kfree(sc->bufptr); - sc->bufptr = NULL; + kfree(ah->bufptr); + ah->bufptr = NULL; } @@ -895,10 +891,9 @@ ath5k_desc_free(struct ath5k_softc *sc) \**************/ static struct ath5k_txq * -ath5k_txq_setup(struct ath5k_softc *sc, +ath5k_txq_setup(struct ath5k_hw *ah, int qtype, int subtype) { - struct ath5k_hw *ah = sc->ah; struct ath5k_txq *txq; struct ath5k_txq_info qi = { .tqi_subtype = subtype, @@ -932,13 +927,13 @@ ath5k_txq_setup(struct ath5k_softc *sc, */ return ERR_PTR(qnum); } - if (qnum >= ARRAY_SIZE(sc->txqs)) { - ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n", - qnum, ARRAY_SIZE(sc->txqs)); + if (qnum >= ARRAY_SIZE(ah->txqs)) { + ATH5K_ERR(ah, "hw qnum %u out of range, max %tu!\n", + qnum, ARRAY_SIZE(ah->txqs)); ath5k_hw_release_tx_queue(ah, qnum); return ERR_PTR(-EINVAL); } - txq = &sc->txqs[qnum]; + txq = &ah->txqs[qnum]; if (!txq->setup) { txq->qnum = qnum; txq->link = NULL; @@ -950,7 +945,7 @@ ath5k_txq_setup(struct ath5k_softc *sc, txq->txq_poll_mark = false; txq->txq_stuck = 0; } - return &sc->txqs[qnum]; + return &ah->txqs[qnum]; } static int @@ -970,18 +965,17 @@ ath5k_beaconq_setup(struct ath5k_hw *ah) } static int -ath5k_beaconq_config(struct ath5k_softc *sc) +ath5k_beaconq_config(struct ath5k_hw *ah) { - struct ath5k_hw *ah = sc->ah; struct ath5k_txq_info qi; int ret; - ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); + ret = ath5k_hw_get_tx_queueprops(ah, ah->bhalq, &qi); if (ret) goto err; - if (sc->opmode == NL80211_IFTYPE_AP || - sc->opmode == NL80211_IFTYPE_MESH_POINT) { + if (ah->opmode == NL80211_IFTYPE_AP || + ah->opmode == NL80211_IFTYPE_MESH_POINT) { /* * Always burst out beacon and CAB traffic * (aifs = cwmin = cwmax = 0) @@ -989,7 +983,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc) qi.tqi_aifs = 0; qi.tqi_cw_min = 0; qi.tqi_cw_max = 0; - } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { + } else if (ah->opmode == NL80211_IFTYPE_ADHOC) { /* * Adhoc mode; backoff between 0 and (2 * cw_min). */ @@ -998,17 +992,17 @@ ath5k_beaconq_config(struct ath5k_softc *sc) qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN; } - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n", qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max); - ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi); + ret = ath5k_hw_set_tx_queueprops(ah, ah->bhalq, &qi); if (ret) { - ATH5K_ERR(sc, "%s: unable to update parameters for beacon " + ATH5K_ERR(ah, "%s: unable to update parameters for beacon " "hardware queue!\n", __func__); goto err; } - ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */ + ret = ath5k_hw_reset_tx_queue(ah, ah->bhalq); /* push to h/w */ if (ret) goto err; @@ -1017,7 +1011,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc) if (ret) goto err; - qi.tqi_ready_time = (sc->bintval * 80) / 100; + qi.tqi_ready_time = (ah->bintval * 80) / 100; ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); if (ret) goto err; @@ -1030,7 +1024,7 @@ err: /** * ath5k_drain_tx_buffs - Empty tx buffers * - * @sc The &struct ath5k_softc + * @ah The &struct ath5k_hw * * Empty tx buffers from all queues in preparation * of a reset or during shutdown. @@ -1039,26 +1033,26 @@ err: * we do not need to block ath5k_tx_tasklet */ static void -ath5k_drain_tx_buffs(struct ath5k_softc *sc) +ath5k_drain_tx_buffs(struct ath5k_hw *ah) { struct ath5k_txq *txq; struct ath5k_buf *bf, *bf0; int i; - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { - if (sc->txqs[i].setup) { - txq = &sc->txqs[i]; + for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { + if (ah->txqs[i].setup) { + txq = &ah->txqs[i]; spin_lock_bh(&txq->lock); list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf); + ath5k_debug_printtxbuf(ah, bf); - ath5k_txbuf_free_skb(sc, bf); + ath5k_txbuf_free_skb(ah, bf); - spin_lock_bh(&sc->txbuflock); - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; + spin_lock_bh(&ah->txbuflock); + list_move_tail(&bf->list, &ah->txbuf); + ah->txbuf_len++; txq->txq_len--; - spin_unlock_bh(&sc->txbuflock); + spin_unlock_bh(&ah->txbuflock); } txq->link = NULL; txq->txq_poll_mark = false; @@ -1068,14 +1062,14 @@ ath5k_drain_tx_buffs(struct ath5k_softc *sc) } static void -ath5k_txq_release(struct ath5k_softc *sc) +ath5k_txq_release(struct ath5k_hw *ah) { - struct ath5k_txq *txq = sc->txqs; + struct ath5k_txq *txq = ah->txqs; unsigned int i; - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++) + for (i = 0; i < ARRAY_SIZE(ah->txqs); i++, txq++) if (txq->setup) { - ath5k_hw_release_tx_queue(sc->ah, txq->qnum); + ath5k_hw_release_tx_queue(ah, txq->qnum); txq->setup = false; } } @@ -1089,33 +1083,32 @@ ath5k_txq_release(struct ath5k_softc *sc) * Enable the receive h/w following a reset. */ static int -ath5k_rx_start(struct ath5k_softc *sc) +ath5k_rx_start(struct ath5k_hw *ah) { - struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); struct ath5k_buf *bf; int ret; common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", common->cachelsz, common->rx_bufsize); - spin_lock_bh(&sc->rxbuflock); - sc->rxlink = NULL; - list_for_each_entry(bf, &sc->rxbuf, list) { - ret = ath5k_rxbuf_setup(sc, bf); + spin_lock_bh(&ah->rxbuflock); + ah->rxlink = NULL; + list_for_each_entry(bf, &ah->rxbuf, list) { + ret = ath5k_rxbuf_setup(ah, bf); if (ret != 0) { - spin_unlock_bh(&sc->rxbuflock); + spin_unlock_bh(&ah->rxbuflock); goto err; } } - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); + bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list); ath5k_hw_set_rxdp(ah, bf->daddr); - spin_unlock_bh(&sc->rxbuflock); + spin_unlock_bh(&ah->rxbuflock); ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ - ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */ + ath5k_update_bssid_mask_and_opmode(ah, NULL); /* set filters, etc. */ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ return 0; @@ -1131,21 +1124,19 @@ err: * does. */ static void -ath5k_rx_stop(struct ath5k_softc *sc) +ath5k_rx_stop(struct ath5k_hw *ah) { - struct ath5k_hw *ah = sc->ah; ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ - ath5k_debug_printrxbuffs(sc, ah); + ath5k_debug_printrxbuffs(ah); } static unsigned int -ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb, +ath5k_rx_decrypted(struct ath5k_hw *ah, struct sk_buff *skb, struct ath5k_rx_status *rs) { - struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); struct ieee80211_hdr *hdr = (void *)skb->data; unsigned int keyix, hlen; @@ -1172,10 +1163,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb, static void -ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, +ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb, struct ieee80211_rx_status *rxs) { - struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_common *common = ath5k_hw_common(ah); u64 tsf, bc_tstamp; u32 hw_tu; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; @@ -1188,11 +1179,11 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, * have updated the local TSF. We have to work around various * hardware bugs, though... */ - tsf = ath5k_hw_get_tsf64(sc->ah); + tsf = ath5k_hw_get_tsf64(ah); bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp); hw_tu = TSF_TO_TU(tsf); - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", (unsigned long long)bc_tstamp, (unsigned long long)rxs->mactime, @@ -1211,7 +1202,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, * received, not like mac80211 which defines it at the start. */ if (bc_tstamp > rxs->mactime) { - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "fixing mactime from %llx to %llx\n", (unsigned long long)rxs->mactime, (unsigned long long)tsf); @@ -1224,25 +1215,24 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, * beacons. This also takes care of synchronizing beacon sending * times with other stations. */ - if (hw_tu >= sc->nexttbtt) - ath5k_beacon_update_timers(sc, bc_tstamp); + if (hw_tu >= ah->nexttbtt) + ath5k_beacon_update_timers(ah, bc_tstamp); /* Check if the beacon timers are still correct, because a TSF * update might have created a window between them - for a * longer description see the comment of this function: */ - if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) { - ath5k_beacon_update_timers(sc, bc_tstamp); - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + if (!ath5k_hw_check_beacon_timers(ah, ah->bintval)) { + ath5k_beacon_update_timers(ah, bc_tstamp); + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "fixed beacon timers after beacon receive\n"); } } } static void -ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) +ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi) { struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); /* only beacons from our BSSID */ @@ -1324,7 +1314,7 @@ static int ath5k_remove_padding(struct sk_buff *skb) } static void -ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, +ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb, struct ath5k_rx_status *rs) { struct ieee80211_rx_status *rxs; @@ -1357,37 +1347,37 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, * impossible to comply to that. This affects IBSS merge only * right now, so it's not too bad... */ - rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); + rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp); rxs->flag |= RX_FLAG_MACTIME_MPDU; - rxs->freq = sc->curchan->center_freq; - rxs->band = sc->curchan->band; + rxs->freq = ah->curchan->center_freq; + rxs->band = ah->curchan->band; - rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; + rxs->signal = ah->ah_noise_floor + rs->rs_rssi; rxs->antenna = rs->rs_antenna; if (rs->rs_antenna > 0 && rs->rs_antenna < 5) - sc->stats.antenna_rx[rs->rs_antenna]++; + ah->stats.antenna_rx[rs->rs_antenna]++; else - sc->stats.antenna_rx[0]++; /* invalid */ + ah->stats.antenna_rx[0]++; /* invalid */ - rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate); - rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); + rxs->rate_idx = ath5k_hw_to_driver_rix(ah, rs->rs_rate); + rxs->flag |= ath5k_rx_decrypted(ah, skb, rs); if (rxs->rate_idx >= 0 && rs->rs_rate == - sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short) + ah->sbands[ah->curchan->band].bitrates[rxs->rate_idx].hw_value_short) rxs->flag |= RX_FLAG_SHORTPRE; - trace_ath5k_rx(sc, skb); + trace_ath5k_rx(ah, skb); - ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); + ath5k_update_beacon_rssi(ah, skb, rs->rs_rssi); /* check beacons in IBSS mode */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_check_ibss_tsf(sc, skb, rxs); + if (ah->opmode == NL80211_IFTYPE_ADHOC) + ath5k_check_ibss_tsf(ah, skb, rxs); - ieee80211_rx(sc->hw, skb); + ieee80211_rx(ah->hw, skb); } /** ath5k_frame_receive_ok() - Do we want to receive this frame or not? @@ -1396,20 +1386,20 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, * statistics. Return true if we want this frame, false if not. */ static bool -ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) +ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs) { - sc->stats.rx_all_count++; - sc->stats.rx_bytes_count += rs->rs_datalen; + ah->stats.rx_all_count++; + ah->stats.rx_bytes_count += rs->rs_datalen; if (unlikely(rs->rs_status)) { if (rs->rs_status & AR5K_RXERR_CRC) - sc->stats.rxerr_crc++; + ah->stats.rxerr_crc++; if (rs->rs_status & AR5K_RXERR_FIFO) - sc->stats.rxerr_fifo++; + ah->stats.rxerr_fifo++; if (rs->rs_status & AR5K_RXERR_PHY) { - sc->stats.rxerr_phy++; + ah->stats.rxerr_phy++; if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32) - sc->stats.rxerr_phy_code[rs->rs_phyerr]++; + ah->stats.rxerr_phy_code[rs->rs_phyerr]++; return false; } if (rs->rs_status & AR5K_RXERR_DECRYPT) { @@ -1423,13 +1413,13 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) * * XXX do key cache faulting */ - sc->stats.rxerr_decrypt++; + ah->stats.rxerr_decrypt++; if (rs->rs_keyix == AR5K_RXKEYIX_INVALID && !(rs->rs_status & AR5K_RXERR_CRC)) return true; } if (rs->rs_status & AR5K_RXERR_MIC) { - sc->stats.rxerr_mic++; + ah->stats.rxerr_mic++; return true; } @@ -1439,26 +1429,26 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) } if (unlikely(rs->rs_more)) { - sc->stats.rxerr_jumbo++; + ah->stats.rxerr_jumbo++; return false; } return true; } static void -ath5k_set_current_imask(struct ath5k_softc *sc) +ath5k_set_current_imask(struct ath5k_hw *ah) { enum ath5k_int imask; unsigned long flags; - spin_lock_irqsave(&sc->irqlock, flags); - imask = sc->imask; - if (sc->rx_pending) + spin_lock_irqsave(&ah->irqlock, flags); + imask = ah->imask; + if (ah->rx_pending) imask &= ~AR5K_INT_RX_ALL; - if (sc->tx_pending) + if (ah->tx_pending) imask &= ~AR5K_INT_TX_ALL; - ath5k_hw_set_imr(sc->ah, imask); - spin_unlock_irqrestore(&sc->irqlock, flags); + ath5k_hw_set_imr(ah, imask); + spin_unlock_irqrestore(&ah->irqlock, flags); } static void @@ -1467,39 +1457,38 @@ ath5k_tasklet_rx(unsigned long data) struct ath5k_rx_status rs = {}; struct sk_buff *skb, *next_skb; dma_addr_t next_skb_addr; - struct ath5k_softc *sc = (void *)data; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = (void *)data; struct ath_common *common = ath5k_hw_common(ah); struct ath5k_buf *bf; struct ath5k_desc *ds; int ret; - spin_lock(&sc->rxbuflock); - if (list_empty(&sc->rxbuf)) { - ATH5K_WARN(sc, "empty rx buf pool\n"); + spin_lock(&ah->rxbuflock); + if (list_empty(&ah->rxbuf)) { + ATH5K_WARN(ah, "empty rx buf pool\n"); goto unlock; } do { - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); + bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list); BUG_ON(bf->skb == NULL); skb = bf->skb; ds = bf->desc; /* bail if HW is still using self-linked descriptor */ - if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr) + if (ath5k_hw_get_rxdp(ah) == bf->daddr) break; - ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); + ret = ah->ah_proc_rx_desc(ah, ds, &rs); if (unlikely(ret == -EINPROGRESS)) break; else if (unlikely(ret)) { - ATH5K_ERR(sc, "error in processing rx descriptor\n"); - sc->stats.rxerr_proc++; + ATH5K_ERR(ah, "error in processing rx descriptor\n"); + ah->stats.rxerr_proc++; break; } - if (ath5k_receive_frame_ok(sc, &rs)) { - next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); + if (ath5k_receive_frame_ok(ah, &rs)) { + next_skb = ath5k_rx_skb_alloc(ah, &next_skb_addr); /* * If we can't replace bf->skb with a new skb under @@ -1508,24 +1497,24 @@ ath5k_tasklet_rx(unsigned long data) if (!next_skb) goto next; - dma_unmap_single(sc->dev, bf->skbaddr, + dma_unmap_single(ah->dev, bf->skbaddr, common->rx_bufsize, DMA_FROM_DEVICE); skb_put(skb, rs.rs_datalen); - ath5k_receive_frame(sc, skb, &rs); + ath5k_receive_frame(ah, skb, &rs); bf->skb = next_skb; bf->skbaddr = next_skb_addr; } next: - list_move_tail(&bf->list, &sc->rxbuf); - } while (ath5k_rxbuf_setup(sc, bf) == 0); + list_move_tail(&bf->list, &ah->rxbuf); + } while (ath5k_rxbuf_setup(ah, bf) == 0); unlock: - spin_unlock(&sc->rxbuflock); - sc->rx_pending = false; - ath5k_set_current_imask(sc); + spin_unlock(&ah->rxbuflock); + ah->rx_pending = false; + ath5k_set_current_imask(ah); } @@ -1537,12 +1526,12 @@ void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath5k_txq *txq) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; struct ath5k_buf *bf; unsigned long flags; int padsize; - trace_ath5k_tx(sc, skb, txq); + trace_ath5k_tx(ah, skb, txq); /* * The hardware expects the header padded to 4 byte boundaries. @@ -1550,7 +1539,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, */ padsize = ath5k_add_padding(skb); if (padsize < 0) { - ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" + ATH5K_ERR(ah, "tx hdrlen not %%4: not enough" " headroom to pad"); goto drop_packet; } @@ -1559,28 +1548,28 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX) ieee80211_stop_queue(hw, txq->qnum); - spin_lock_irqsave(&sc->txbuflock, flags); - if (list_empty(&sc->txbuf)) { - ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); - spin_unlock_irqrestore(&sc->txbuflock, flags); + spin_lock_irqsave(&ah->txbuflock, flags); + if (list_empty(&ah->txbuf)) { + ATH5K_ERR(ah, "no further txbuf available, dropping packet\n"); + spin_unlock_irqrestore(&ah->txbuflock, flags); ieee80211_stop_queues(hw); goto drop_packet; } - bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); + bf = list_first_entry(&ah->txbuf, struct ath5k_buf, list); list_del(&bf->list); - sc->txbuf_len--; - if (list_empty(&sc->txbuf)) + ah->txbuf_len--; + if (list_empty(&ah->txbuf)) ieee80211_stop_queues(hw); - spin_unlock_irqrestore(&sc->txbuflock, flags); + spin_unlock_irqrestore(&ah->txbuflock, flags); bf->skb = skb; - if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { + if (ath5k_txbuf_setup(ah, bf, txq, padsize)) { bf->skb = NULL; - spin_lock_irqsave(&sc->txbuflock, flags); - list_add_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock_irqrestore(&sc->txbuflock, flags); + spin_lock_irqsave(&ah->txbuflock, flags); + list_add_tail(&bf->list, &ah->txbuf); + ah->txbuf_len++; + spin_unlock_irqrestore(&ah->txbuflock, flags); goto drop_packet; } return; @@ -1590,15 +1579,15 @@ drop_packet: } static void -ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, +ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, struct ath5k_txq *txq, struct ath5k_tx_status *ts) { struct ieee80211_tx_info *info; u8 tries[3]; int i; - sc->stats.tx_all_count++; - sc->stats.tx_bytes_count += skb->len; + ah->stats.tx_all_count++; + ah->stats.tx_bytes_count += skb->len; info = IEEE80211_SKB_CB(skb); tries[0] = info->status.rates[0].count; @@ -1618,15 +1607,15 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, info->status.rates[ts->ts_final_idx + 1].idx = -1; if (unlikely(ts->ts_status)) { - sc->stats.ack_fail++; + ah->stats.ack_fail++; if (ts->ts_status & AR5K_TXERR_FILT) { info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - sc->stats.txerr_filt++; + ah->stats.txerr_filt++; } if (ts->ts_status & AR5K_TXERR_XRETRY) - sc->stats.txerr_retry++; + ah->stats.txerr_retry++; if (ts->ts_status & AR5K_TXERR_FIFO) - sc->stats.txerr_fifo++; + ah->stats.txerr_fifo++; } else { info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ts->ts_rssi; @@ -1642,16 +1631,16 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, ath5k_remove_padding(skb); if (ts->ts_antenna > 0 && ts->ts_antenna < 5) - sc->stats.antenna_tx[ts->ts_antenna]++; + ah->stats.antenna_tx[ts->ts_antenna]++; else - sc->stats.antenna_tx[0]++; /* invalid */ + ah->stats.antenna_tx[0]++; /* invalid */ - trace_ath5k_tx_complete(sc, skb, txq, ts); - ieee80211_tx_status(sc->hw, skb); + trace_ath5k_tx_complete(ah, skb, txq, ts); + ieee80211_tx_status(ah->hw, skb); } static void -ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) +ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq) { struct ath5k_tx_status ts = {}; struct ath5k_buf *bf, *bf0; @@ -1668,11 +1657,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) if (bf->skb != NULL) { ds = bf->desc; - ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); + ret = ah->ah_proc_tx_desc(ah, ds, &ts); if (unlikely(ret == -EINPROGRESS)) break; else if (unlikely(ret)) { - ATH5K_ERR(sc, + ATH5K_ERR(ah, "error %d while processing " "queue %u\n", ret, txq->qnum); break; @@ -1681,9 +1670,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) skb = bf->skb; bf->skb = NULL; - dma_unmap_single(sc->dev, bf->skbaddr, skb->len, + dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); - ath5k_tx_frame_completed(sc, skb, txq, &ts); + ath5k_tx_frame_completed(ah, skb, txq, &ts); } /* @@ -1692,31 +1681,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) * host memory and moved on. * Always keep the last descriptor to avoid HW races... */ - if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) { - spin_lock(&sc->txbuflock); - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; + if (ath5k_hw_get_txdp(ah, txq->qnum) != bf->daddr) { + spin_lock(&ah->txbuflock); + list_move_tail(&bf->list, &ah->txbuf); + ah->txbuf_len++; txq->txq_len--; - spin_unlock(&sc->txbuflock); + spin_unlock(&ah->txbuflock); } } spin_unlock(&txq->lock); if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4) - ieee80211_wake_queue(sc->hw, txq->qnum); + ieee80211_wake_queue(ah->hw, txq->qnum); } static void ath5k_tasklet_tx(unsigned long data) { int i; - struct ath5k_softc *sc = (void *)data; + struct ath5k_hw *ah = (void *)data; for (i = 0; i < AR5K_NUM_TX_QUEUES; i++) - if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) - ath5k_tx_processq(sc, &sc->txqs[i]); + if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i))) + ath5k_tx_processq(ah, &ah->txqs[i]); - sc->tx_pending = false; - ath5k_set_current_imask(sc); + ah->tx_pending = false; + ath5k_set_current_imask(ah); } @@ -1728,25 +1717,24 @@ ath5k_tasklet_tx(unsigned long data) * Setup the beacon frame for transmit. */ static int -ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) +ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf) { struct sk_buff *skb = bf->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath5k_hw *ah = sc->ah; struct ath5k_desc *ds; int ret = 0; u8 antenna; u32 flags; const int padsize = 0; - bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len, DMA_TO_DEVICE); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " "skbaddr %llx\n", skb, skb->data, skb->len, (unsigned long long)bf->skbaddr); - if (dma_mapping_error(sc->dev, bf->skbaddr)) { - ATH5K_ERR(sc, "beacon DMA mapping failed\n"); + if (dma_mapping_error(ah->dev, bf->skbaddr)) { + ATH5K_ERR(ah, "beacon DMA mapping failed\n"); return -EIO; } @@ -1754,7 +1742,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) antenna = ah->ah_tx_ant; flags = AR5K_TXDESC_NOACK; - if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { + if (ah->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { ds->ds_link = bf->daddr; /* self-linked */ flags |= AR5K_TXDESC_VEOL; } else @@ -1779,7 +1767,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) * on all of them. */ if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) - antenna = sc->bsent & 4 ? 2 : 1; + antenna = ah->bsent & 4 ? 2 : 1; /* FIXME: If we are in g mode and rate is a CCK rate @@ -1788,8 +1776,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ds->ds_data = bf->skbaddr; ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), padsize, - AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), - ieee80211_get_tx_rate(sc->hw, info)->hw_value, + AR5K_PKT_TYPE_BEACON, (ah->power_level * 2), + ieee80211_get_tx_rate(ah->hw, info)->hw_value, 1, AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); if (ret) @@ -1797,7 +1785,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) return 0; err_unmap: - dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); + dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@ -1812,7 +1800,7 @@ int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { int ret; - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; struct ath5k_vif *avf = (void *)vif->drv_priv; struct sk_buff *skb; @@ -1828,9 +1816,9 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out; } - ath5k_txbuf_free_skb(sc, avf->bbuf); + ath5k_txbuf_free_skb(ah, avf->bbuf); avf->bbuf->skb = skb; - ret = ath5k_beacon_setup(sc, avf->bbuf); + ret = ath5k_beacon_setup(ah, avf->bbuf); if (ret) avf->bbuf->skb = NULL; out: @@ -1846,15 +1834,14 @@ out: * or user context from ath5k_beacon_config. */ static void -ath5k_beacon_send(struct ath5k_softc *sc) +ath5k_beacon_send(struct ath5k_hw *ah) { - struct ath5k_hw *ah = sc->ah; struct ieee80211_vif *vif; struct ath5k_vif *avf; struct ath5k_buf *bf; struct sk_buff *skb; - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "in beacon_send\n"); /* * Check if the previous beacon has gone out. If @@ -1863,47 +1850,47 @@ ath5k_beacon_send(struct ath5k_softc *sc) * indicate a problem and should not occur. If we * miss too many consecutive beacons reset the device. */ - if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { - sc->bmisscount++; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "missed %u consecutive beacons\n", sc->bmisscount); - if (sc->bmisscount > 10) { /* NB: 10 is a guess */ - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + if (unlikely(ath5k_hw_num_tx_pending(ah, ah->bhalq) != 0)) { + ah->bmisscount++; + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, + "missed %u consecutive beacons\n", ah->bmisscount); + if (ah->bmisscount > 10) { /* NB: 10 is a guess */ + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "stuck beacon time (%u missed)\n", - sc->bmisscount); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + ah->bmisscount); + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "stuck beacon, resetting\n"); - ieee80211_queue_work(sc->hw, &sc->reset_work); + ieee80211_queue_work(ah->hw, &ah->reset_work); } return; } - if (unlikely(sc->bmisscount != 0)) { - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + if (unlikely(ah->bmisscount != 0)) { + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "resume beacon xmit after %u misses\n", - sc->bmisscount); - sc->bmisscount = 0; + ah->bmisscount); + ah->bmisscount = 0; } - if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) || - sc->opmode == NL80211_IFTYPE_MESH_POINT) { + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) || + ah->opmode == NL80211_IFTYPE_MESH_POINT) { u64 tsf = ath5k_hw_get_tsf64(ah); u32 tsftu = TSF_TO_TU(tsf); - int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval; - vif = sc->bslot[(slot + 1) % ATH_BCBUF]; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + int slot = ((tsftu % ah->bintval) * ATH_BCBUF) / ah->bintval; + vif = ah->bslot[(slot + 1) % ATH_BCBUF]; + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "tsf %llx tsftu %x intval %u slot %u vif %p\n", - (unsigned long long)tsf, tsftu, sc->bintval, slot, vif); + (unsigned long long)tsf, tsftu, ah->bintval, slot, vif); } else /* only one interface */ - vif = sc->bslot[0]; + vif = ah->bslot[0]; if (!vif) return; avf = (void *)vif->drv_priv; bf = avf->bbuf; - if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_MONITOR)) { - ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); + if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION || + ah->opmode == NL80211_IFTYPE_MONITOR)) { + ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); return; } @@ -1912,40 +1899,40 @@ ath5k_beacon_send(struct ath5k_softc *sc) * This should never fail since we check above that no frames * are still pending on the queue. */ - if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) { - ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); + if (unlikely(ath5k_hw_stop_beacon_queue(ah, ah->bhalq))) { + ATH5K_WARN(ah, "beacon queue %u didn't start/stop ?\n", ah->bhalq); /* NB: hw still stops DMA, so proceed */ } /* refresh the beacon for AP or MESH mode */ - if (sc->opmode == NL80211_IFTYPE_AP || - sc->opmode == NL80211_IFTYPE_MESH_POINT) - ath5k_beacon_update(sc->hw, vif); + if (ah->opmode == NL80211_IFTYPE_AP || + ah->opmode == NL80211_IFTYPE_MESH_POINT) + ath5k_beacon_update(ah->hw, vif); - trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]); + trace_ath5k_tx(ah, bf->skb, &ah->txqs[ah->bhalq]); - ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); - ath5k_hw_start_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", - sc->bhalq, (unsigned long long)bf->daddr, bf->desc); + ath5k_hw_set_txdp(ah, ah->bhalq, bf->daddr); + ath5k_hw_start_tx_dma(ah, ah->bhalq); + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", + ah->bhalq, (unsigned long long)bf->daddr, bf->desc); - skb = ieee80211_get_buffered_bc(sc->hw, vif); + skb = ieee80211_get_buffered_bc(ah->hw, vif); while (skb) { - ath5k_tx_queue(sc->hw, skb, sc->cabq); + ath5k_tx_queue(ah->hw, skb, ah->cabq); - if (sc->cabq->txq_len >= sc->cabq->txq_max) + if (ah->cabq->txq_len >= ah->cabq->txq_max) break; - skb = ieee80211_get_buffered_bc(sc->hw, vif); + skb = ieee80211_get_buffered_bc(ah->hw, vif); } - sc->bsent++; + ah->bsent++; } /** * ath5k_beacon_update_timers - update beacon timers * - * @sc: struct ath5k_softc pointer we are operating on + * @ah: struct ath5k_hw pointer we are operating on * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a * beacon timer update based on the current HW TSF. * @@ -1959,17 +1946,16 @@ ath5k_beacon_send(struct ath5k_softc *sc) * function to have it all together in one place. */ void -ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) +ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) { - struct ath5k_hw *ah = sc->ah; u32 nexttbtt, intval, hw_tu, bc_tu; u64 hw_tsf; - intval = sc->bintval & AR5K_BEACON_PERIOD; - if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) { + intval = ah->bintval & AR5K_BEACON_PERIOD; + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) { intval /= ATH_BCBUF; /* staggered multi-bss beacons */ if (intval < 15) - ATH5K_WARN(sc, "intval %u is too low, min 15\n", + ATH5K_WARN(ah, "intval %u is too low, min 15\n", intval); } if (WARN_ON(!intval)) @@ -2008,7 +1994,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) * automatically update the TSF and then we need to reconfigure * the timers. */ - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "need to wait for HW TSF sync\n"); return; } else { @@ -2023,7 +2009,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) } #undef FUDGE - sc->nexttbtt = nexttbtt; + ah->nexttbtt = nexttbtt; intval |= AR5K_BEACON_ENA; ath5k_hw_init_beacon(ah, nexttbtt, intval); @@ -2033,20 +2019,20 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) * of this function */ if (bc_tsf == -1) - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "reconfigured timers based on HW TSF\n"); else if (bc_tsf == 0) - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "reset HW TSF and timers\n"); else - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "updated timers based on beacon TSF\n"); - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", (unsigned long long) bc_tsf, (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt); - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", intval & AR5K_BEACON_PERIOD, intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); @@ -2055,22 +2041,21 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) /** * ath5k_beacon_config - Configure the beacon queues and interrupts * - * @sc: struct ath5k_softc pointer we are operating on + * @ah: struct ath5k_hw pointer we are operating on * * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA * interrupts to detect TSF updates only. */ void -ath5k_beacon_config(struct ath5k_softc *sc) +ath5k_beacon_config(struct ath5k_hw *ah) { - struct ath5k_hw *ah = sc->ah; unsigned long flags; - spin_lock_irqsave(&sc->block, flags); - sc->bmisscount = 0; - sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); + spin_lock_irqsave(&ah->block, flags); + ah->bmisscount = 0; + ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); - if (sc->enable_beacon) { + if (ah->enable_beacon) { /* * In IBSS mode we use a self-linked tx descriptor and let the * hardware send the beacons automatically. We have to load it @@ -2078,27 +2063,27 @@ ath5k_beacon_config(struct ath5k_softc *sc) * We use the SWBA interrupt only to keep track of the beacon * timers in order to detect automatic TSF updates. */ - ath5k_beaconq_config(sc); + ath5k_beaconq_config(ah); - sc->imask |= AR5K_INT_SWBA; + ah->imask |= AR5K_INT_SWBA; - if (sc->opmode == NL80211_IFTYPE_ADHOC) { + if (ah->opmode == NL80211_IFTYPE_ADHOC) { if (ath5k_hw_hasveol(ah)) - ath5k_beacon_send(sc); + ath5k_beacon_send(ah); } else - ath5k_beacon_update_timers(sc, -1); + ath5k_beacon_update_timers(ah, -1); } else { - ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq); + ath5k_hw_stop_beacon_queue(ah, ah->bhalq); } - ath5k_hw_set_imr(ah, sc->imask); + ath5k_hw_set_imr(ah, ah->imask); mmiowb(); - spin_unlock_irqrestore(&sc->block, flags); + spin_unlock_irqrestore(&ah->block, flags); } static void ath5k_tasklet_beacon(unsigned long data) { - struct ath5k_softc *sc = (struct ath5k_softc *) data; + struct ath5k_hw *ah = (struct ath5k_hw *) data; /* * Software beacon alert--time to send a beacon. @@ -2108,20 +2093,20 @@ static void ath5k_tasklet_beacon(unsigned long data) * transmission time) in order to detect whether * automatic TSF updates happened. */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) { + if (ah->opmode == NL80211_IFTYPE_ADHOC) { /* XXX: only if VEOL supported */ - u64 tsf = ath5k_hw_get_tsf64(sc->ah); - sc->nexttbtt += sc->bintval; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + u64 tsf = ath5k_hw_get_tsf64(ah); + ah->nexttbtt += ah->bintval; + ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "SWBA nexttbtt: %x hw_tu: %x " "TSF: %llx\n", - sc->nexttbtt, + ah->nexttbtt, TSF_TO_TU(tsf), (unsigned long long) tsf); } else { - spin_lock(&sc->block); - ath5k_beacon_send(sc); - spin_unlock(&sc->block); + spin_lock(&ah->block); + ath5k_beacon_send(ah); + spin_unlock(&ah->block); } } @@ -2138,12 +2123,12 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) /* run ANI only when full calibration is not active */ ah->ah_cal_next_ani = jiffies + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); - tasklet_schedule(&ah->ah_sc->ani_tasklet); + tasklet_schedule(&ah->ani_tasklet); } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { ah->ah_cal_next_full = jiffies + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); - tasklet_schedule(&ah->ah_sc->calib); + tasklet_schedule(&ah->calib); } /* we could use SWI to generate enough interrupts to meet our * calibration interval requirements, if necessary: @@ -2151,44 +2136,43 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) } static void -ath5k_schedule_rx(struct ath5k_softc *sc) +ath5k_schedule_rx(struct ath5k_hw *ah) { - sc->rx_pending = true; - tasklet_schedule(&sc->rxtq); + ah->rx_pending = true; + tasklet_schedule(&ah->rxtq); } static void -ath5k_schedule_tx(struct ath5k_softc *sc) +ath5k_schedule_tx(struct ath5k_hw *ah) { - sc->tx_pending = true; - tasklet_schedule(&sc->txtq); + ah->tx_pending = true; + tasklet_schedule(&ah->txtq); } static irqreturn_t ath5k_intr(int irq, void *dev_id) { - struct ath5k_softc *sc = dev_id; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = dev_id; enum ath5k_int status; unsigned int counter = 1000; - if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || + if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) || ((ath5k_get_bus_type(ah) != ATH_AHB) && !ath5k_hw_is_intr_pending(ah)))) return IRQ_NONE; do { ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ - ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", - status, sc->imask); + ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", + status, ah->imask); if (unlikely(status & AR5K_INT_FATAL)) { /* * Fatal errors are unrecoverable. * Typically these are caused by DMA errors. */ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "fatal int, resetting\n"); - ieee80211_queue_work(sc->hw, &sc->reset_work); + ieee80211_queue_work(ah->hw, &ah->reset_work); } else if (unlikely(status & AR5K_INT_RXORN)) { /* * Receive buffers are full. Either the bus is busy or @@ -2199,16 +2183,16 @@ ath5k_intr(int irq, void *dev_id) * We don't know exactly which versions need a reset - * this guess is copied from the HAL. */ - sc->stats.rxorn_intr++; + ah->stats.rxorn_intr++; if (ah->ah_mac_srev < AR5K_SREV_AR5212) { - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "rx overrun, resetting\n"); - ieee80211_queue_work(sc->hw, &sc->reset_work); + ieee80211_queue_work(ah->hw, &ah->reset_work); } else - ath5k_schedule_rx(sc); + ath5k_schedule_rx(ah); } else { if (status & AR5K_INT_SWBA) - tasklet_hi_schedule(&sc->beacontq); + tasklet_hi_schedule(&ah->beacontq); if (status & AR5K_INT_RXEOL) { /* @@ -2216,27 +2200,27 @@ ath5k_intr(int irq, void *dev_id) * RXE bit is written, but it doesn't work at * least on older hardware revs. */ - sc->stats.rxeol_intr++; + ah->stats.rxeol_intr++; } if (status & AR5K_INT_TXURN) { /* bump tx trigger level */ ath5k_hw_update_tx_triglevel(ah, true); } if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) - ath5k_schedule_rx(sc); + ath5k_schedule_rx(ah); if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC | AR5K_INT_TXERR | AR5K_INT_TXEOL)) - ath5k_schedule_tx(sc); + ath5k_schedule_tx(ah); if (status & AR5K_INT_BMISS) { /* TODO */ } if (status & AR5K_INT_MIB) { - sc->stats.mib_intr++; + ah->stats.mib_intr++; ath5k_hw_update_mib_counters(ah); ath5k_ani_mib_intr(ah); } if (status & AR5K_INT_GPIO) - tasklet_schedule(&sc->rf_kill.toggleq); + tasklet_schedule(&ah->rf_kill.toggleq); } @@ -2245,11 +2229,11 @@ ath5k_intr(int irq, void *dev_id) } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); - if (sc->rx_pending || sc->tx_pending) - ath5k_set_current_imask(sc); + if (ah->rx_pending || ah->tx_pending) + ath5k_set_current_imask(ah); if (unlikely(!counter)) - ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); + ATH5K_WARN(ah, "too many interrupts, giving up for now\n"); ath5k_intr_calibration_poll(ah); @@ -2263,28 +2247,27 @@ ath5k_intr(int irq, void *dev_id) static void ath5k_tasklet_calibrate(unsigned long data) { - struct ath5k_softc *sc = (void *)data; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = (void *)data; /* Only full calibration for now */ ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; - ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", - ieee80211_frequency_to_channel(sc->curchan->center_freq), - sc->curchan->hw_value); + ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", + ieee80211_frequency_to_channel(ah->curchan->center_freq), + ah->curchan->hw_value); if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { /* * Rfgain is out of bounds, reset the chip * to load new gain values. */ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); - ieee80211_queue_work(sc->hw, &sc->reset_work); + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "calibration, resetting\n"); + ieee80211_queue_work(ah->hw, &ah->reset_work); } - if (ath5k_hw_phy_calibrate(ah, sc->curchan)) - ATH5K_ERR(sc, "calibration of channel %u failed\n", + if (ath5k_hw_phy_calibrate(ah, ah->curchan)) + ATH5K_ERR(ah, "calibration of channel %u failed\n", ieee80211_frequency_to_channel( - sc->curchan->center_freq)); + ah->curchan->center_freq)); /* Noise floor calibration interrupts rx/tx path while I/Q calibration * doesn't. @@ -2303,8 +2286,7 @@ ath5k_tasklet_calibrate(unsigned long data) static void ath5k_tasklet_ani(unsigned long data) { - struct ath5k_softc *sc = (void *)data; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = (void *)data; ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; ath5k_ani_calibration(ah); @@ -2315,21 +2297,21 @@ ath5k_tasklet_ani(unsigned long data) static void ath5k_tx_complete_poll_work(struct work_struct *work) { - struct ath5k_softc *sc = container_of(work, struct ath5k_softc, + struct ath5k_hw *ah = container_of(work, struct ath5k_hw, tx_complete_work.work); struct ath5k_txq *txq; int i; bool needreset = false; - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { - if (sc->txqs[i].setup) { - txq = &sc->txqs[i]; + for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { + if (ah->txqs[i].setup) { + txq = &ah->txqs[i]; spin_lock_bh(&txq->lock); if (txq->txq_len > 1) { if (txq->txq_poll_mark) { - ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, + ATH5K_DBG(ah, ATH5K_DEBUG_XMIT, "TX queue stuck %d\n", txq->qnum); needreset = true; @@ -2345,14 +2327,14 @@ ath5k_tx_complete_poll_work(struct work_struct *work) } if (needreset) { - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "TX queues stuck, resetting\n"); - ath5k_reset(sc, NULL, true); + ath5k_reset(ah, NULL, true); } - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, + ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work, msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); } @@ -2362,15 +2344,15 @@ ath5k_tx_complete_poll_work(struct work_struct *work) \*************************/ int __devinit -ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) +ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) { - struct ieee80211_hw *hw = sc->hw; + struct ieee80211_hw *hw = ah->hw; struct ath_common *common; int ret; int csz; /* Initialize driver private data */ - SET_IEEE80211_DEV(hw, sc->dev); + SET_IEEE80211_DEV(hw, ah->dev); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | @@ -2393,39 +2375,29 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) * Mark the device as detached to avoid processing * interrupts until setup is complete. */ - __set_bit(ATH_STAT_INVALID, sc->status); + __set_bit(ATH_STAT_INVALID, ah->status); - sc->opmode = NL80211_IFTYPE_STATION; - sc->bintval = 1000; - mutex_init(&sc->lock); - spin_lock_init(&sc->rxbuflock); - spin_lock_init(&sc->txbuflock); - spin_lock_init(&sc->block); - spin_lock_init(&sc->irqlock); + ah->opmode = NL80211_IFTYPE_STATION; + ah->bintval = 1000; + mutex_init(&ah->lock); + spin_lock_init(&ah->rxbuflock); + spin_lock_init(&ah->txbuflock); + spin_lock_init(&ah->block); + spin_lock_init(&ah->irqlock); /* Setup interrupt handler */ - ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); + ret = request_irq(ah->irq, ath5k_intr, IRQF_SHARED, "ath", ah); if (ret) { - ATH5K_ERR(sc, "request_irq failed\n"); + ATH5K_ERR(ah, "request_irq failed\n"); goto err; } - /* If we passed the test, malloc an ath5k_hw struct */ - sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); - if (!sc->ah) { - ret = -ENOMEM; - ATH5K_ERR(sc, "out of memory\n"); - goto err_irq; - } - - sc->ah->ah_sc = sc; - sc->ah->ah_iobase = sc->iobase; - common = ath5k_hw_common(sc->ah); + common = ath5k_hw_common(ah); common->ops = &ath5k_common_ops; common->bus_ops = bus_ops; - common->ah = sc->ah; + common->ah = ah; common->hw = hw; - common->priv = sc; + common->priv = ah; common->clockrate = 40; /* @@ -2438,12 +2410,12 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) spin_lock_init(&common->cc_lock); /* Initialize device */ - ret = ath5k_hw_init(sc); + ret = ath5k_hw_init(ah); if (ret) - goto err_free_ah; + goto err_irq; /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { + if (ah->ah_version == AR5K_AR5212) { hw->max_rates = 4; hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT, AR5K_INIT_RETRY_LONG); @@ -2456,77 +2428,74 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) if (ret) goto err_ah; - ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), - sc->ah->ah_mac_srev, - sc->ah->ah_phy_revision); + ATH5K_INFO(ah, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", + ath5k_chip_name(AR5K_VERSION_MAC, ah->ah_mac_srev), + ah->ah_mac_srev, + ah->ah_phy_revision); - if (!sc->ah->ah_single_chip) { + if (!ah->ah_single_chip) { /* Single chip radio (!RF5111) */ - if (sc->ah->ah_radio_5ghz_revision && - !sc->ah->ah_radio_2ghz_revision) { + if (ah->ah_radio_5ghz_revision && + !ah->ah_radio_2ghz_revision) { /* No 5GHz support -> report 2GHz radio */ if (!test_bit(AR5K_MODE_11A, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); + ah->ah_radio_5ghz_revision), + ah->ah_radio_5ghz_revision); /* No 2GHz support (5110 and some * 5GHz only cards) -> report 5GHz radio */ } else if (!test_bit(AR5K_MODE_11B, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); + ah->ah_radio_5ghz_revision), + ah->ah_radio_5ghz_revision); /* Multiband radio */ } else { - ATH5K_INFO(sc, "RF%s multiband radio found" + ATH5K_INFO(ah, "RF%s multiband radio found" " (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); + ah->ah_radio_5ghz_revision), + ah->ah_radio_5ghz_revision); } } /* Multi chip radio (RF5111 - RF2111) -> * report both 2GHz/5GHz radios */ - else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + else if (ah->ah_radio_5ghz_revision && + ah->ah_radio_2ghz_revision) { + ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ah->ah_radio_5ghz_revision), + ah->ah_radio_5ghz_revision); + ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); + ah->ah_radio_2ghz_revision), + ah->ah_radio_2ghz_revision); } } - ath5k_debug_init_device(sc); + ath5k_debug_init_device(ah); /* ready to process interrupts */ - __clear_bit(ATH_STAT_INVALID, sc->status); + __clear_bit(ATH_STAT_INVALID, ah->status); return 0; err_ah: - ath5k_hw_deinit(sc->ah); -err_free_ah: - kfree(sc->ah); + ath5k_hw_deinit(ah); err_irq: - free_irq(sc->irq, sc); + free_irq(ah->irq, ah); err: return ret; } static int -ath5k_stop_locked(struct ath5k_softc *sc) +ath5k_stop_locked(struct ath5k_hw *ah) { - struct ath5k_hw *ah = sc->ah; - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", - test_bit(ATH_STAT_INVALID, sc->status)); + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "invalid %u\n", + test_bit(ATH_STAT_INVALID, ah->status)); /* * Shutdown the hardware and driver: @@ -2543,37 +2512,36 @@ ath5k_stop_locked(struct ath5k_softc *sc) * Note that some of this work is not possible if the * hardware is gone (invalid). */ - ieee80211_stop_queues(sc->hw); + ieee80211_stop_queues(ah->hw); - if (!test_bit(ATH_STAT_INVALID, sc->status)) { - ath5k_led_off(sc); + if (!test_bit(ATH_STAT_INVALID, ah->status)) { + ath5k_led_off(ah); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->irq); - ath5k_rx_stop(sc); + synchronize_irq(ah->irq); + ath5k_rx_stop(ah); ath5k_hw_dma_stop(ah); - ath5k_drain_tx_buffs(sc); + ath5k_drain_tx_buffs(ah); ath5k_hw_phy_disable(ah); } return 0; } -int -ath5k_init_hw(struct ath5k_softc *sc) +int ath5k_start(struct ieee80211_hw *hw) { - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ath_common *common = ath5k_hw_common(ah); int ret, i; - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "mode %d\n", ah->opmode); /* * Stop anything previously setup. This is safe * no matter this is the first time through or not. */ - ath5k_stop_locked(sc); + ath5k_stop_locked(ah); /* * The basic interface to setting the hardware in a good @@ -2582,12 +2550,12 @@ ath5k_init_hw(struct ath5k_softc *sc) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ - sc->curchan = sc->hw->conf.channel; - sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | + ah->curchan = ah->hw->conf.channel; + ah->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; - ret = ath5k_reset(sc, NULL, false); + ret = ath5k_reset(ah, NULL, false); if (ret) goto done; @@ -2604,29 +2572,29 @@ ath5k_init_hw(struct ath5k_softc *sc) * rate */ ah->ah_ack_bitrate_high = true; - for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) - sc->bslot[i] = NULL; + for (i = 0; i < ARRAY_SIZE(ah->bslot); i++) + ah->bslot[i] = NULL; ret = 0; done: mmiowb(); - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, + ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work, msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); return ret; } -static void ath5k_stop_tasklets(struct ath5k_softc *sc) +static void ath5k_stop_tasklets(struct ath5k_hw *ah) { - sc->rx_pending = false; - sc->tx_pending = false; - tasklet_kill(&sc->rxtq); - tasklet_kill(&sc->txtq); - tasklet_kill(&sc->calib); - tasklet_kill(&sc->beacontq); - tasklet_kill(&sc->ani_tasklet); + ah->rx_pending = false; + ah->tx_pending = false; + tasklet_kill(&ah->rxtq); + tasklet_kill(&ah->txtq); + tasklet_kill(&ah->calib); + tasklet_kill(&ah->beacontq); + tasklet_kill(&ah->ani_tasklet); } /* @@ -2635,14 +2603,14 @@ static void ath5k_stop_tasklets(struct ath5k_softc *sc) * if another thread does a system call and the thread doing the * stop is preempted). */ -int -ath5k_stop_hw(struct ath5k_softc *sc) +void ath5k_stop(struct ieee80211_hw *hw) { + struct ath5k_hw *ah = hw->priv; int ret; - mutex_lock(&sc->lock); - ret = ath5k_stop_locked(sc); - if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { + mutex_lock(&ah->lock); + ret = ath5k_stop_locked(ah); + if (ret == 0 && !test_bit(ATH_STAT_INVALID, ah->status)) { /* * Don't set the card in full sleep mode! * @@ -2663,69 +2631,66 @@ ath5k_stop_hw(struct ath5k_softc *sc) * and Sam's HAL do anyway). Instead Perform a full reset * on the device (same as initial state after attach) and * leave it idle (keep MAC/BB on warm reset) */ - ret = ath5k_hw_on_hold(sc->ah); + ret = ath5k_hw_on_hold(ah); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "putting device to sleep\n"); } mmiowb(); - mutex_unlock(&sc->lock); - - ath5k_stop_tasklets(sc); + mutex_unlock(&ah->lock); - cancel_delayed_work_sync(&sc->tx_complete_work); + ath5k_stop_tasklets(ah); - ath5k_rfkill_hw_stop(sc->ah); + cancel_delayed_work_sync(&ah->tx_complete_work); - return ret; + ath5k_rfkill_hw_stop(ah); } /* * Reset the hardware. If chan is not NULL, then also pause rx/tx * and change to the given channel. * - * This should be called with sc->lock. + * This should be called with ah->lock. */ static int -ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, +ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, bool skip_pcu) { - struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); int ret, ani_mode; bool fast; - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n"); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->irq); - ath5k_stop_tasklets(sc); + synchronize_irq(ah->irq); + ath5k_stop_tasklets(ah); /* Save ani mode and disable ANI during * reset. If we don't we might get false * PHY error interrupts. */ - ani_mode = ah->ah_sc->ani_state.ani_mode; + ani_mode = ah->ani_state.ani_mode; ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF); /* We are going to empty hw queues * so we should also free any remaining * tx buffers */ - ath5k_drain_tx_buffs(sc); + ath5k_drain_tx_buffs(ah); if (chan) - sc->curchan = chan; + ah->curchan = chan; fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, skip_pcu); + ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu); if (ret) { - ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); + ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret); goto err; } - ret = ath5k_rx_start(sc); + ret = ath5k_rx_start(ah); if (ret) { - ATH5K_ERR(sc, "can't start recv logic\n"); + ATH5K_ERR(ah, "can't start recv logic\n"); goto err; } @@ -2737,7 +2702,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); /* clear survey data and cycle counters */ - memset(&sc->survey, 0, sizeof(sc->survey)); + memset(&ah->survey, 0, sizeof(ah->survey)); spin_lock_bh(&common->cc_lock); ath_hw_cycle_counters_update(common); memset(&common->cc_survey, 0, sizeof(common->cc_survey)); @@ -2753,12 +2718,12 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, * * XXX needed? */ -/* ath5k_chan_change(sc, c); */ +/* ath5k_chan_change(ah, c); */ - ath5k_beacon_config(sc); + ath5k_beacon_config(ah); /* intrs are enabled by ath5k_beacon_config */ - ieee80211_wake_queues(sc->hw); + ieee80211_wake_queues(ah->hw); return 0; err: @@ -2767,20 +2732,19 @@ err: static void ath5k_reset_work(struct work_struct *work) { - struct ath5k_softc *sc = container_of(work, struct ath5k_softc, + struct ath5k_hw *ah = container_of(work, struct ath5k_hw, reset_work); - mutex_lock(&sc->lock); - ath5k_reset(sc, NULL, true); - mutex_unlock(&sc->lock); + mutex_lock(&ah->lock); + ath5k_reset(ah, NULL, true); + mutex_unlock(&ah->lock); } static int __devinit ath5k_init(struct ieee80211_hw *hw) { - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); struct ath5k_txq *txq; u8 mac[ETH_ALEN] = {}; @@ -2799,7 +2763,7 @@ ath5k_init(struct ieee80211_hw *hw) if (ret < 0) goto err; if (ret > 0) - __set_bit(ATH_STAT_MRRETRY, sc->status); + __set_bit(ATH_STAT_MRRETRY, ah->status); /* * Collect the channel list. The 802.11 layer @@ -2809,16 +2773,16 @@ ath5k_init(struct ieee80211_hw *hw) */ ret = ath5k_setup_bands(hw); if (ret) { - ATH5K_ERR(sc, "can't get channels\n"); + ATH5K_ERR(ah, "can't get channels\n"); goto err; } /* * Allocate tx+rx descriptors and populate the lists. */ - ret = ath5k_desc_alloc(sc); + ret = ath5k_desc_alloc(ah); if (ret) { - ATH5K_ERR(sc, "can't allocate descriptors\n"); + ATH5K_ERR(ah, "can't allocate descriptors\n"); goto err; } @@ -2830,14 +2794,14 @@ ath5k_init(struct ieee80211_hw *hw) */ ret = ath5k_beaconq_setup(ah); if (ret < 0) { - ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); + ATH5K_ERR(ah, "can't setup a beacon xmit queue\n"); goto err_desc; } - sc->bhalq = ret; - sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); - if (IS_ERR(sc->cabq)) { - ATH5K_ERR(sc, "can't setup cab queue\n"); - ret = PTR_ERR(sc->cabq); + ah->bhalq = ret; + ah->cabq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_CAB, 0); + if (IS_ERR(ah->cabq)) { + ATH5K_ERR(ah, "can't setup cab queue\n"); + ret = PTR_ERR(ah->cabq); goto err_bhal; } @@ -2846,97 +2810,97 @@ ath5k_init(struct ieee80211_hw *hw) if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) { /* This order matches mac80211's queue priority, so we can * directly use the mac80211 queue number without any mapping */ - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); + txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); + ATH5K_ERR(ah, "can't setup xmit queue\n"); ret = PTR_ERR(txq); goto err_queues; } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); + txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); + ATH5K_ERR(ah, "can't setup xmit queue\n"); ret = PTR_ERR(txq); goto err_queues; } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); + txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); + ATH5K_ERR(ah, "can't setup xmit queue\n"); ret = PTR_ERR(txq); goto err_queues; } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); + txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); + ATH5K_ERR(ah, "can't setup xmit queue\n"); ret = PTR_ERR(txq); goto err_queues; } hw->queues = 4; } else { /* older hardware (5210) can only support one data queue */ - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); + txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); + ATH5K_ERR(ah, "can't setup xmit queue\n"); ret = PTR_ERR(txq); goto err_queues; } hw->queues = 1; } - tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); - tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); - tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); - tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); - tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); + tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah); + tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah); + tasklet_init(&ah->calib, ath5k_tasklet_calibrate, (unsigned long)ah); + tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah); + tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah); - INIT_WORK(&sc->reset_work, ath5k_reset_work); - INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); + INIT_WORK(&ah->reset_work, ath5k_reset_work); + INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work); ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); if (ret) { - ATH5K_ERR(sc, "unable to read address from EEPROM\n"); + ATH5K_ERR(ah, "unable to read address from EEPROM\n"); goto err_queues; } SET_IEEE80211_PERM_ADDR(hw, mac); - memcpy(&sc->lladdr, mac, ETH_ALEN); + memcpy(&ah->lladdr, mac, ETH_ALEN); /* All MAC address bits matter for ACKs */ - ath5k_update_bssid_mask_and_opmode(sc, NULL); + ath5k_update_bssid_mask_and_opmode(ah, NULL); regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); if (ret) { - ATH5K_ERR(sc, "can't initialize regulatory system\n"); + ATH5K_ERR(ah, "can't initialize regulatory system\n"); goto err_queues; } ret = ieee80211_register_hw(hw); if (ret) { - ATH5K_ERR(sc, "can't register ieee80211 hw\n"); + ATH5K_ERR(ah, "can't register ieee80211 hw\n"); goto err_queues; } if (!ath_is_world_regd(regulatory)) regulatory_hint(hw->wiphy, regulatory->alpha2); - ath5k_init_leds(sc); + ath5k_init_leds(ah); - ath5k_sysfs_register(sc); + ath5k_sysfs_register(ah); return 0; err_queues: - ath5k_txq_release(sc); + ath5k_txq_release(ah); err_bhal: - ath5k_hw_release_tx_queue(ah, sc->bhalq); + ath5k_hw_release_tx_queue(ah, ah->bhalq); err_desc: - ath5k_desc_free(sc); + ath5k_desc_free(ah); err: return ret; } void -ath5k_deinit_softc(struct ath5k_softc *sc) +ath5k_deinit_softc(struct ath5k_hw *ah) { - struct ieee80211_hw *hw = sc->hw; + struct ieee80211_hw *hw = ah->hw; /* * NB: the order of these is important: @@ -2952,24 +2916,23 @@ ath5k_deinit_softc(struct ath5k_softc *sc) * Other than that, it's straightforward... */ ieee80211_unregister_hw(hw); - ath5k_desc_free(sc); - ath5k_txq_release(sc); - ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); - ath5k_unregister_leds(sc); + ath5k_desc_free(ah); + ath5k_txq_release(ah); + ath5k_hw_release_tx_queue(ah, ah->bhalq); + ath5k_unregister_leds(ah); - ath5k_sysfs_unregister(sc); + ath5k_sysfs_unregister(ah); /* * NB: can't reclaim these until after ieee80211_ifdetach * returns because we'll get called back to reclaim node * state and potentially want to use them. */ - ath5k_hw_deinit(sc->ah); - kfree(sc->ah); - free_irq(sc->irq, sc); + ath5k_hw_deinit(ah); + free_irq(ah->irq, ah); } bool -ath5k_any_vif_assoc(struct ath5k_softc *sc) +ath5k_any_vif_assoc(struct ath5k_hw *ah) { struct ath5k_vif_iter_data iter_data; iter_data.hw_macaddr = NULL; @@ -2977,7 +2940,7 @@ ath5k_any_vif_assoc(struct ath5k_softc *sc) iter_data.need_set_hw_addr = false; iter_data.found_active = true; - ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, + ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter, &iter_data); return iter_data.any_assoc; } @@ -2985,8 +2948,7 @@ ath5k_any_vif_assoc(struct ath5k_softc *sc) void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable) { - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; u32 rfilt; rfilt = ath5k_hw_get_rx_filter(ah); if (enable) @@ -2994,5 +2956,5 @@ ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable) else rfilt &= ~AR5K_RX_FILTER_BEACON; ath5k_hw_set_rx_filter(ah, rfilt); - sc->filter_flags = rfilt; + ah->filter_flags = rfilt; } diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 0a98777..a81f28d 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -45,23 +45,13 @@ #include <linux/list.h> #include <linux/wireless.h> #include <linux/if_ether.h> -#include <linux/leds.h> #include <linux/rfkill.h> #include <linux/workqueue.h> #include "ath5k.h" -#include "debug.h" -#include "ani.h" - #include "../regd.h" #include "../ath.h" -#define ATH_RXBUF 40 /* number of RX buffers */ -#define ATH_TXBUF 200 /* number of TX buffers */ -#define ATH_BCBUF 4 /* number of beacon buffers */ -#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ -#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ - struct ath5k_buf { struct list_head list; struct ath5k_desc *desc; /* virtual addr of desc */ @@ -70,94 +60,6 @@ struct ath5k_buf { dma_addr_t skbaddr;/* physical addr of skb data */ }; -/* - * Data transmit queue state. One of these exists for each - * hardware transmit queue. Packets sent to us from above - * are assigned to queues based on their priority. Not all - * devices support a complete set of hardware transmit queues. - * For those devices the array sc_ac2q will map multiple - * priorities to fewer hardware queues (typically all to one - * hardware queue). - */ -struct ath5k_txq { - unsigned int qnum; /* hardware q number */ - u32 *link; /* link ptr in last TX desc */ - struct list_head q; /* transmit queue */ - spinlock_t lock; /* lock on q and link */ - bool setup; - int txq_len; /* number of queued buffers */ - int txq_max; /* max allowed num of queued buffers */ - bool txq_poll_mark; - unsigned int txq_stuck; /* informational counter */ -}; - -#define ATH5K_LED_MAX_NAME_LEN 31 - -/* - * State for LED triggers - */ -struct ath5k_led { - char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ - struct ath5k_softc *sc; /* driver state */ - struct led_classdev led_dev; /* led classdev */ -}; - -/* Rfkill */ -struct ath5k_rfkill { - /* GPIO PIN for rfkill */ - u16 gpio; - /* polarity of rfkill GPIO PIN */ - bool polarity; - /* RFKILL toggle tasklet */ - struct tasklet_struct toggleq; -}; - -/* statistics */ -struct ath5k_statistics { - /* antenna use */ - unsigned int antenna_rx[5]; /* frames count per antenna RX */ - unsigned int antenna_tx[5]; /* frames count per antenna TX */ - - /* frame errors */ - unsigned int rx_all_count; /* all RX frames, including errors */ - unsigned int tx_all_count; /* all TX frames, including errors */ - unsigned int rx_bytes_count; /* all RX bytes, including errored pkts - * and the MAC headers for each packet - */ - unsigned int tx_bytes_count; /* all TX bytes, including errored pkts - * and the MAC headers and padding for - * each packet. - */ - unsigned int rxerr_crc; - unsigned int rxerr_phy; - unsigned int rxerr_phy_code[32]; - unsigned int rxerr_fifo; - unsigned int rxerr_decrypt; - unsigned int rxerr_mic; - unsigned int rxerr_proc; - unsigned int rxerr_jumbo; - unsigned int txerr_retry; - unsigned int txerr_fifo; - unsigned int txerr_filt; - - /* MIB counters */ - unsigned int ack_fail; - unsigned int rts_fail; - unsigned int rts_ok; - unsigned int fcs_error; - unsigned int beacons; - - unsigned int mib_intr; - unsigned int rxorn_intr; - unsigned int rxeol_intr; -}; - -#if CHAN_DEBUG -#define ATH_CHAN_MAX (26 + 26 + 26 + 200 + 200) -#else -#define ATH_CHAN_MAX (14 + 14 + 14 + 252 + 20) -#endif - struct ath5k_vif { bool assoc; /* are we associated or not */ enum nl80211_iftype opmode; @@ -166,104 +68,6 @@ struct ath5k_vif { u8 lladdr[ETH_ALEN]; }; -/* Software Carrier, keeps track of the driver state - * associated with an instance of a device */ -struct ath5k_softc { - struct pci_dev *pdev; - struct device *dev; /* for dma mapping */ - int irq; - u16 devid; - void __iomem *iobase; /* address of the device */ - struct mutex lock; /* dev-level lock */ - struct ieee80211_hw *hw; /* IEEE 802.11 common */ - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - struct ieee80211_channel channels[ATH_CHAN_MAX]; - struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - enum nl80211_iftype opmode; - struct ath5k_hw *ah; /* Atheros HW */ - -#ifdef CONFIG_ATH5K_DEBUG - struct ath5k_dbg_info debug; /* debug info */ -#endif /* CONFIG_ATH5K_DEBUG */ - - struct ath5k_buf *bufptr; /* allocated buffer ptr */ - struct ath5k_desc *desc; /* TX/RX descriptors */ - dma_addr_t desc_daddr; /* DMA (physical) address */ - size_t desc_len; /* size of TX/RX descriptors */ - - DECLARE_BITMAP(status, 6); -#define ATH_STAT_INVALID 0 /* disable hardware accesses */ -#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ -#define ATH_STAT_PROMISC 2 -#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ -#define ATH_STAT_STARTED 4 /* opened & irqs enabled */ -#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ - - unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ - struct ieee80211_channel *curchan; /* current h/w channel */ - - u16 nvifs; - - enum ath5k_int imask; /* interrupt mask copy */ - - spinlock_t irqlock; - bool rx_pending; /* rx tasklet pending */ - bool tx_pending; /* tx tasklet pending */ - - u8 lladdr[ETH_ALEN]; - u8 bssidmask[ETH_ALEN]; - - unsigned int led_pin, /* GPIO pin for driving LED */ - led_on; /* pin setting for LED on */ - - struct work_struct reset_work; /* deferred chip reset */ - - unsigned int rxbufsize; /* rx size based on mtu */ - struct list_head rxbuf; /* receive buffer */ - spinlock_t rxbuflock; - u32 *rxlink; /* link ptr in last RX desc */ - struct tasklet_struct rxtq; /* rx intr tasklet */ - struct ath5k_led rx_led; /* rx led */ - - struct list_head txbuf; /* transmit buffer */ - spinlock_t txbuflock; - unsigned int txbuf_len; /* buf count in txbuf list */ - struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ - struct tasklet_struct txtq; /* tx intr tasklet */ - struct ath5k_led tx_led; /* tx led */ - - struct ath5k_rfkill rf_kill; - - struct tasklet_struct calib; /* calibration tasklet */ - - spinlock_t block; /* protects beacon */ - struct tasklet_struct beacontq; /* beacon intr tasklet */ - struct list_head bcbuf; /* beacon buffer */ - struct ieee80211_vif *bslot[ATH_BCBUF]; - u16 num_ap_vifs; - u16 num_adhoc_vifs; - unsigned int bhalq, /* SW q for outgoing beacons */ - bmisscount, /* missed beacon transmits */ - bintval, /* beacon interval in TU */ - bsent; - unsigned int nexttbtt; /* next beacon time in TU */ - struct ath5k_txq *cabq; /* content after beacon */ - - int power_level; /* Requested tx power in dBm */ - bool assoc; /* associate state */ - bool enable_beacon; /* true if beacons are on */ - - struct ath5k_statistics stats; - - struct ath5k_ani_state ani_state; - struct tasklet_struct ani_tasklet; /* ANI calibration */ - - struct delayed_work tx_complete_work; - - struct survey_info survey; /* collected survey info */ -}; - struct ath5k_vif_iter_data { const u8 *hw_macaddr; u8 mask[ETH_ALEN]; @@ -277,9 +81,10 @@ struct ath5k_vif_iter_data { void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif); -#define ath5k_hw_hasbssidmask(_ah) \ - (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) -#define ath5k_hw_hasveol(_ah) \ - (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) +/* Check whether BSSID mask is supported */ +#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212) + +/* Check whether virtual EOL is supported */ +#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210) #endif diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index c752982..eefe670 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -112,51 +112,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) return 0; } -/* Main function used by the driver part to check caps */ -int ath5k_hw_get_capability(struct ath5k_hw *ah, - enum ath5k_capability_type cap_type, - u32 capability, u32 *result) -{ - switch (cap_type) { - case AR5K_CAP_NUM_TXQUEUES: - if (result) { - if (ah->ah_version == AR5K_AR5210) - *result = AR5K_NUM_TX_QUEUES_NOQCU; - else - *result = AR5K_NUM_TX_QUEUES; - goto yes; - } - case AR5K_CAP_VEOL: - goto yes; - case AR5K_CAP_COMPRESSION: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - case AR5K_CAP_BURST: - goto yes; - case AR5K_CAP_TPC: - goto yes; - case AR5K_CAP_BSSIDMASK: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - case AR5K_CAP_XR: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - default: - goto no; - } - -no: - return -EINVAL; -yes: - return 0; -} - /* * TODO: Following functions should be part of a new function * set_capability diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4edca70..ccca724 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -157,10 +157,10 @@ static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) static int reg_show(struct seq_file *seq, void *p) { - struct ath5k_softc *sc = seq->private; + struct ath5k_hw *ah = seq->private; struct reg *r = p; seq_printf(seq, "%-25s0x%08x\n", r->name, - ath5k_hw_reg_read(sc->ah, r->addr)); + ath5k_hw_reg_read(ah, r->addr)); return 0; } @@ -197,42 +197,41 @@ static const struct file_operations fops_registers = { static ssize_t read_file_beacon(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = file->private_data; char buf[500]; unsigned int len = 0; unsigned int v; u64 tsf; - v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); + v = ath5k_hw_reg_read(ah, AR5K_BEACON); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n", - "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); + "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP)); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n", - "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT)); + "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT)); - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); + v = ath5k_hw_reg_read(ah, AR5K_TIMER0); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", "AR5K_TIMER0 (TBTT)", v, v); - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); + v = ath5k_hw_reg_read(ah, AR5K_TIMER1); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", "AR5K_TIMER1 (DMA)", v, v >> 3); - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); + v = ath5k_hw_reg_read(ah, AR5K_TIMER2); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", "AR5K_TIMER2 (SWBA)", v, v >> 3); - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); + v = ath5k_hw_reg_read(ah, AR5K_TIMER3); len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n", "AR5K_TIMER3 (ATIM)", v, v); - tsf = ath5k_hw_get_tsf64(sc->ah); + tsf = ath5k_hw_get_tsf64(ah); len += snprintf(buf + len, sizeof(buf) - len, "TSF\t\t0x%016llx\tTU: %08x\n", (unsigned long long)tsf, TSF_TO_TU(tsf)); @@ -247,8 +246,7 @@ static ssize_t write_file_beacon(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = file->private_data; char buf[20]; if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) @@ -279,9 +277,9 @@ static ssize_t write_file_reset(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); - ieee80211_queue_work(sc->hw, &sc->reset_work); + struct ath5k_hw *ah = file->private_data; + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); + ieee80211_queue_work(ah->hw, &ah->reset_work); return count; } @@ -318,23 +316,23 @@ static const struct { static ssize_t read_file_debug(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; char buf[700]; unsigned int len = 0; unsigned int i; len += snprintf(buf + len, sizeof(buf) - len, - "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); + "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level); for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { len += snprintf(buf + len, sizeof(buf) - len, "%10s %c 0x%08x - %s\n", dbg_info[i].name, - sc->debug.level & dbg_info[i].level ? '+' : ' ', + ah->debug.level & dbg_info[i].level ? '+' : ' ', dbg_info[i].level, dbg_info[i].desc); } len += snprintf(buf + len, sizeof(buf) - len, "%10s %c 0x%08x - %s\n", dbg_info[i].name, - sc->debug.level == dbg_info[i].level ? '+' : ' ', + ah->debug.level == dbg_info[i].level ? '+' : ' ', dbg_info[i].level, dbg_info[i].desc); if (len > sizeof(buf)) @@ -347,7 +345,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; unsigned int i; char buf[20]; @@ -357,7 +355,7 @@ static ssize_t write_file_debug(struct file *file, for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { if (strncmp(buf, dbg_info[i].name, strlen(dbg_info[i].name)) == 0) { - sc->debug.level ^= dbg_info[i].level; /* toggle bit */ + ah->debug.level ^= dbg_info[i].level; /* toggle bit */ break; } } @@ -378,33 +376,33 @@ static const struct file_operations fops_debug = { static ssize_t read_file_antenna(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; char buf[700]; unsigned int len = 0; unsigned int i; unsigned int v; len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n", - sc->ah->ah_ant_mode); + ah->ah_ant_mode); len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n", - sc->ah->ah_def_ant); + ah->ah_def_ant); len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n", - sc->ah->ah_tx_ant); + ah->ah_tx_ant); len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n"); - for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { + for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) { len += snprintf(buf + len, sizeof(buf) - len, "[antenna %d]\t%d\t%d\n", - i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]); + i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]); } len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n", - sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]); + ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]); - v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA); + v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); len += snprintf(buf + len, sizeof(buf) - len, "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v); - v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1); + v = ath5k_hw_reg_read(ah, AR5K_STA_ID1); len += snprintf(buf + len, sizeof(buf) - len, "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n", (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0); @@ -418,25 +416,25 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf, "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n", (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0); - v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL); + v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL); len += snprintf(buf + len, sizeof(buf) - len, "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n", (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0); - v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART); + v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART); len += snprintf(buf + len, sizeof(buf) - len, "AR5K_PHY_RESTART_DIV_GC\t\t%x\n", (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S); - v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV); + v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV); len += snprintf(buf + len, sizeof(buf) - len, "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); - v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0); + v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0); len += snprintf(buf + len, sizeof(buf) - len, "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v); - v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1); + v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1); len += snprintf(buf + len, sizeof(buf) - len, "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v); @@ -450,7 +448,7 @@ static ssize_t write_file_antenna(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; unsigned int i; char buf[20]; @@ -458,18 +456,18 @@ static ssize_t write_file_antenna(struct file *file, return -EFAULT; if (strncmp(buf, "diversity", 9) == 0) { - ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); printk(KERN_INFO "ath5k debug: enable diversity\n"); } else if (strncmp(buf, "fixed-a", 7) == 0) { - ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A); printk(KERN_INFO "ath5k debugfs: fixed antenna A\n"); } else if (strncmp(buf, "fixed-b", 7) == 0) { - ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B); printk(KERN_INFO "ath5k debug: fixed antenna B\n"); } else if (strncmp(buf, "clear", 5) == 0) { - for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { - sc->stats.antenna_rx[i] = 0; - sc->stats.antenna_tx[i] = 0; + for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) { + ah->stats.antenna_rx[i] = 0; + ah->stats.antenna_tx[i] = 0; } printk(KERN_INFO "ath5k debug: cleared antenna stats\n"); } @@ -489,13 +487,13 @@ static const struct file_operations fops_antenna = { static ssize_t read_file_misc(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; char buf[700]; unsigned int len = 0; - u32 filt = ath5k_hw_get_rx_filter(sc->ah); + u32 filt = ath5k_hw_get_rx_filter(ah); len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n", - sc->bssidmask); + ah->bssidmask); len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ", filt); if (filt & AR5K_RX_FILTER_UCAST) @@ -524,7 +522,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211"); len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n", - ath_opmode_to_string(sc->opmode), sc->opmode); + ath_opmode_to_string(ah->opmode), ah->opmode); if (len > sizeof(buf)) len = sizeof(buf); @@ -544,8 +542,8 @@ static const struct file_operations fops_misc = { static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; - struct ath5k_statistics *st = &sc->stats; + struct ath5k_hw *ah = file->private_data; + struct ath5k_statistics *st = &ah->stats; char buf[700]; unsigned int len = 0; int i; @@ -621,8 +619,8 @@ static ssize_t write_file_frameerrors(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; - struct ath5k_statistics *st = &sc->stats; + struct ath5k_hw *ah = file->private_data; + struct ath5k_statistics *st = &ah->stats; char buf[20]; if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) @@ -660,16 +658,16 @@ static const struct file_operations fops_frameerrors = { static ssize_t read_file_ani(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; - struct ath5k_statistics *st = &sc->stats; - struct ath5k_ani_state *as = &sc->ani_state; + struct ath5k_hw *ah = file->private_data; + struct ath5k_statistics *st = &ah->stats; + struct ath5k_ani_state *as = &ah->ani_state; char buf[700]; unsigned int len = 0; len += snprintf(buf + len, sizeof(buf) - len, "HW has PHY error counters:\t%s\n", - sc->ah->ah_capabilities.cap_has_phyerr_counters ? + ah->ah_capabilities.cap_has_phyerr_counters ? "yes" : "no"); len += snprintf(buf + len, sizeof(buf) - len, "HW max spur immunity level:\t%d\n", @@ -718,7 +716,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, st->mib_intr); len += snprintf(buf + len, sizeof(buf) - len, "beacon RSSI average:\t%d\n", - (int)ewma_read(&sc->ah->ah_beacon_rssi_avg)); + (int)ewma_read(&ah->ah_beacon_rssi_avg)); #define CC_PRINT(_struct, _field) \ _struct._field, \ @@ -750,14 +748,14 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, as->sum_cck_errors); len += snprintf(buf + len, sizeof(buf) - len, "AR5K_PHYERR_CNT1\t%x\t(=%d)\n", - ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1), + ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1), ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - - ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1))); + ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1))); len += snprintf(buf + len, sizeof(buf) - len, "AR5K_PHYERR_CNT2\t%x\t(=%d)\n", - ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2), + ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2), ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - - ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2))); + ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2))); if (len > sizeof(buf)) len = sizeof(buf); @@ -769,42 +767,42 @@ static ssize_t write_file_ani(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; char buf[20]; if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) return -EFAULT; if (strncmp(buf, "sens-low", 8) == 0) { - ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH); + ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH); } else if (strncmp(buf, "sens-high", 9) == 0) { - ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW); + ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW); } else if (strncmp(buf, "ani-off", 7) == 0) { - ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF); + ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF); } else if (strncmp(buf, "ani-on", 6) == 0) { - ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO); + ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO); } else if (strncmp(buf, "noise-low", 9) == 0) { - ath5k_ani_set_noise_immunity_level(sc->ah, 0); + ath5k_ani_set_noise_immunity_level(ah, 0); } else if (strncmp(buf, "noise-high", 10) == 0) { - ath5k_ani_set_noise_immunity_level(sc->ah, + ath5k_ani_set_noise_immunity_level(ah, ATH5K_ANI_MAX_NOISE_IMM_LVL); } else if (strncmp(buf, "spur-low", 8) == 0) { - ath5k_ani_set_spur_immunity_level(sc->ah, 0); + ath5k_ani_set_spur_immunity_level(ah, 0); } else if (strncmp(buf, "spur-high", 9) == 0) { - ath5k_ani_set_spur_immunity_level(sc->ah, - sc->ani_state.max_spur_level); + ath5k_ani_set_spur_immunity_level(ah, + ah->ani_state.max_spur_level); } else if (strncmp(buf, "fir-low", 7) == 0) { - ath5k_ani_set_firstep_level(sc->ah, 0); + ath5k_ani_set_firstep_level(ah, 0); } else if (strncmp(buf, "fir-high", 8) == 0) { - ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL); + ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); } else if (strncmp(buf, "ofdm-off", 8) == 0) { - ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false); + ath5k_ani_set_ofdm_weak_signal_detection(ah, false); } else if (strncmp(buf, "ofdm-on", 7) == 0) { - ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true); + ath5k_ani_set_ofdm_weak_signal_detection(ah, true); } else if (strncmp(buf, "cck-off", 7) == 0) { - ath5k_ani_set_cck_weak_signal_detection(sc->ah, false); + ath5k_ani_set_cck_weak_signal_detection(ah, false); } else if (strncmp(buf, "cck-on", 6) == 0) { - ath5k_ani_set_cck_weak_signal_detection(sc->ah, true); + ath5k_ani_set_cck_weak_signal_detection(ah, true); } return count; } @@ -823,7 +821,7 @@ static const struct file_operations fops_ani = { static ssize_t read_file_queue(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; char buf[700]; unsigned int len = 0; @@ -832,10 +830,10 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, int i, n; len += snprintf(buf + len, sizeof(buf) - len, - "available txbuffers: %d\n", sc->txbuf_len); + "available txbuffers: %d\n", ah->txbuf_len); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { - txq = &sc->txqs[i]; + for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { + txq = &ah->txqs[i]; len += snprintf(buf + len, sizeof(buf) - len, "%02d: %ssetup\n", i, txq->setup ? "" : "not "); @@ -865,16 +863,16 @@ static ssize_t write_file_queue(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = file->private_data; char buf[20]; if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) return -EFAULT; if (strncmp(buf, "start", 5) == 0) - ieee80211_wake_queues(sc->hw); + ieee80211_wake_queues(ah->hw); else if (strncmp(buf, "stop", 4) == 0) - ieee80211_stop_queues(sc->hw); + ieee80211_stop_queues(ah->hw); return count; } @@ -890,57 +888,57 @@ static const struct file_operations fops_queue = { void -ath5k_debug_init_device(struct ath5k_softc *sc) +ath5k_debug_init_device(struct ath5k_hw *ah) { struct dentry *phydir; - sc->debug.level = ath5k_debug; + ah->debug.level = ath5k_debug; - phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); + phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir); if (!phydir) return; - debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, + debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah, &fops_debug); - debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); + debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers); - debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, + debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah, &fops_beacon); - debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); + debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset); - debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, + debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah, &fops_antenna); - debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); + debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc); - debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, + debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah, &fops_frameerrors); - debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); + debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani); - debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, + debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah, &fops_queue); debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir, - &sc->ah->ah_use_32khz_clock); + &ah->ah_use_32khz_clock); } /* functions used in other places */ void -ath5k_debug_dump_bands(struct ath5k_softc *sc) +ath5k_debug_dump_bands(struct ath5k_hw *ah) { unsigned int b, i; - if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS))) + if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS))) return; - BUG_ON(!sc->sbands); + BUG_ON(!ah->sbands); for (b = 0; b < IEEE80211_NUM_BANDS; b++) { - struct ieee80211_supported_band *band = &sc->sbands[b]; + struct ieee80211_supported_band *band = &ah->sbands[b]; char bname[6]; switch (band->band) { case IEEE80211_BAND_2GHZ: @@ -990,41 +988,41 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, } void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) +ath5k_debug_printrxbuffs(struct ath5k_hw *ah) { struct ath5k_desc *ds; struct ath5k_buf *bf; struct ath5k_rx_status rs = {}; int status; - if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC))) + if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC))) return; printk(KERN_DEBUG "rxdp %x, rxlink %p\n", - ath5k_hw_get_rxdp(ah), sc->rxlink); + ath5k_hw_get_rxdp(ah), ah->rxlink); - spin_lock_bh(&sc->rxbuflock); - list_for_each_entry(bf, &sc->rxbuf, list) { + spin_lock_bh(&ah->rxbuflock); + list_for_each_entry(bf, &ah->rxbuf, list) { ds = bf->desc; status = ah->ah_proc_rx_desc(ah, ds, &rs); if (!status) ath5k_debug_printrxbuf(bf, status == 0, &rs); } - spin_unlock_bh(&sc->rxbuflock); + spin_unlock_bh(&ah->rxbuflock); } void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) +ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf) { struct ath5k_desc *ds = bf->desc; struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; struct ath5k_tx_status ts = {}; int done; - if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC))) + if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC))) return; - done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); + done = ah->ah_proc_tx_desc(ah, bf->desc, &ts); printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 193dd2d..7f37df3 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -61,7 +61,6 @@ #ifndef _ATH5K_DEBUG_H #define _ATH5K_DEBUG_H -struct ath5k_softc; struct ath5k_hw; struct sk_buff; struct ath5k_buf; @@ -127,39 +126,39 @@ enum ath5k_debug_level { } while (0) void -ath5k_debug_init_device(struct ath5k_softc *sc); +ath5k_debug_init_device(struct ath5k_hw *ah); void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); +ath5k_debug_printrxbuffs(struct ath5k_hw *ah); void -ath5k_debug_dump_bands(struct ath5k_softc *sc); +ath5k_debug_dump_bands(struct ath5k_hw *ah); void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); +ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf); #else /* no debugging */ #include <linux/compiler.h> static inline void __attribute__ ((format (printf, 3, 4))) -ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} +ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {} static inline void __attribute__ ((format (printf, 3, 4))) -ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) +ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {} static inline void -ath5k_debug_init_device(struct ath5k_softc *sc) {} +ath5k_debug_init_device(struct ath5k_hw *ah) {} static inline void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} +ath5k_debug_printrxbuffs(struct ath5k_hw *ah) {} static inline void -ath5k_debug_dump_bands(struct ath5k_softc *sc) {} +ath5k_debug_dump_bands(struct ath5k_hw *ah) {} static inline void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} +ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf) {} #endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index f82383b..846535f 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -55,12 +55,12 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, * noise on the channel, so it is important to avoid this. */ if (unlikely(tx_tries0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero retries\n"); + ATH5K_ERR(ah, "zero retries\n"); WARN_ON(1); return -EINVAL; } if (unlikely(tx_rate0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); + ATH5K_ERR(ah, "zero rate\n"); WARN_ON(1); return -EINVAL; } @@ -203,12 +203,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, * noise on the channel, so it is important to avoid this. */ if (unlikely(tx_tries0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero retries\n"); + ATH5K_ERR(ah, "zero retries\n"); WARN_ON(1); return -EINVAL; } if (unlikely(tx_rate0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); + ATH5K_ERR(ah, "zero rate\n"); WARN_ON(1); return -EINVAL; } @@ -316,7 +316,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || (tx_rate2 == 0 && tx_tries2 != 0) || (tx_rate3 == 0 && tx_tries3 != 0))) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); + ATH5K_ERR(ah, "zero rate\n"); WARN_ON(1); return -EINVAL; } diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index b788ecf..0d5d403 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -73,7 +73,7 @@ static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) udelay(100); if (!i) - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + ATH5K_DBG(ah, ATH5K_DEBUG_DMA, "failed to stop RX DMA !\n"); return i ? 0 : -EBUSY; @@ -100,7 +100,7 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) { if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + ATH5K_DBG(ah, ATH5K_DEBUG_DMA, "tried to set RXDP while rx was active !\n"); return -EIO; } @@ -243,7 +243,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) udelay(100); if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + ATH5K_DBG(ah, ATH5K_DEBUG_DMA, "queue %i didn't stop !\n", queue); /* Check for pending frames */ @@ -295,7 +295,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); if (pending) - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + ATH5K_DBG(ah, ATH5K_DEBUG_DMA, "quiet mechanism didn't work q:%i !\n", queue); } @@ -309,7 +309,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Clear register */ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); if (pending) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + ATH5K_DBG(ah, ATH5K_DEBUG_DMA, "tx dma didn't stop (q:%i, frm:%i) !\n", queue, pending); return -EBUSY; @@ -333,7 +333,7 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) int ret; ret = ath5k_hw_stop_tx_dma(ah, queue); if (ret) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, + ATH5K_DBG(ah, ATH5K_DEBUG_DMA, "beacon queue didn't stop !\n"); return -EIO; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index d9e605e..9068b91 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -105,7 +105,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) * big still, waiting on a better value. */ if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { - ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " + ATH5K_ERR(ah, "Invalid max custom EEPROM size: " "%d (0x%04x) max expected: %d (0x%04x)\n", eep_max, eep_max, 3 * AR5K_EEPROM_INFO_MAX, @@ -119,7 +119,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) cksum ^= val; } if (cksum != AR5K_EEPROM_INFO_CKSUM) { - ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " + ATH5K_ERR(ah, "Invalid EEPROM " "checksum: 0x%04x eep_max: 0x%04x (%s)\n", cksum, eep_max, eep_max == AR5K_EEPROM_INFO_MAX ? diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 855d1af..5ab607f 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -1542,7 +1542,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) /* AR5K_MODE_11B */ if (mode > 2) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "unsupported channel mode: %d\n", mode); return -EINVAL; } diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 127bfbd..8c17a00 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -86,26 +86,26 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = { { } }; -void ath5k_led_enable(struct ath5k_softc *sc) +void ath5k_led_enable(struct ath5k_hw *ah) { - if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { - ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); - ath5k_led_off(sc); + if (test_bit(ATH_STAT_LEDSOFT, ah->status)) { + ath5k_hw_set_gpio_output(ah, ah->led_pin); + ath5k_led_off(ah); } } -static void ath5k_led_on(struct ath5k_softc *sc) +static void ath5k_led_on(struct ath5k_hw *ah) { - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); + ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on); } -void ath5k_led_off(struct ath5k_softc *sc) +void ath5k_led_off(struct ath5k_hw *ah) { - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); + ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on); } static void @@ -116,27 +116,27 @@ ath5k_led_brightness_set(struct led_classdev *led_dev, led_dev); if (brightness == LED_OFF) - ath5k_led_off(led->sc); + ath5k_led_off(led->ah); else - ath5k_led_on(led->sc); + ath5k_led_on(led->ah); } static int -ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, +ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led, const char *name, char *trigger) { int err; - led->sc = sc; + led->ah = ah; strncpy(led->name, name, sizeof(led->name)); led->led_dev.name = led->name; led->led_dev.default_trigger = trigger; led->led_dev.brightness_set = ath5k_led_brightness_set; - err = led_classdev_register(sc->dev, &led->led_dev); + err = led_classdev_register(ah->dev, &led->led_dev); if (err) { - ATH5K_WARN(sc, "could not register LED %s\n", name); - led->sc = NULL; + ATH5K_WARN(ah, "could not register LED %s\n", name); + led->ah = NULL; } return err; } @@ -144,30 +144,30 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, static void ath5k_unregister_led(struct ath5k_led *led) { - if (!led->sc) + if (!led->ah) return; led_classdev_unregister(&led->led_dev); - ath5k_led_off(led->sc); - led->sc = NULL; + ath5k_led_off(led->ah); + led->ah = NULL; } -void ath5k_unregister_leds(struct ath5k_softc *sc) +void ath5k_unregister_leds(struct ath5k_hw *ah) { - ath5k_unregister_led(&sc->rx_led); - ath5k_unregister_led(&sc->tx_led); + ath5k_unregister_led(&ah->rx_led); + ath5k_unregister_led(&ah->tx_led); } -int __devinit ath5k_init_leds(struct ath5k_softc *sc) +int __devinit ath5k_init_leds(struct ath5k_hw *ah) { int ret = 0; - struct ieee80211_hw *hw = sc->hw; + struct ieee80211_hw *hw = ah->hw; #ifndef CONFIG_ATHEROS_AR231X - struct pci_dev *pdev = sc->pdev; + struct pci_dev *pdev = ah->pdev; #endif char name[ATH5K_LED_MAX_NAME_LEN + 1]; const struct pci_device_id *match; - if (!sc->pdev) + if (!ah->pdev) return 0; #ifdef CONFIG_ATHEROS_AR231X @@ -176,24 +176,24 @@ int __devinit ath5k_init_leds(struct ath5k_softc *sc) match = pci_match_id(&ath5k_led_devices[0], pdev); #endif if (match) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = ATH_PIN(match->driver_data); - sc->led_on = ATH_POLARITY(match->driver_data); + __set_bit(ATH_STAT_LEDSOFT, ah->status); + ah->led_pin = ATH_PIN(match->driver_data); + ah->led_on = ATH_POLARITY(match->driver_data); } - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) goto out; - ath5k_led_enable(sc); + ath5k_led_enable(ah); snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->rx_led, name, + ret = ath5k_register_led(ah, &ah->rx_led, name, ieee80211_get_rx_led_name(hw)); if (ret) goto out; snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->tx_led, name, + ret = ath5k_register_led(ah, &ah->tx_led, name, ieee80211_get_tx_led_name(hw)); out: return ret; diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 0d5ab34..2a715ca 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -53,44 +53,30 @@ static void ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; u16 qnum = skb_get_queue_mapping(skb); - if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { + if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) { dev_kfree_skb_any(skb); return; } - ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); -} - - -static int -ath5k_start(struct ieee80211_hw *hw) -{ - return ath5k_init_hw(hw->priv); -} - - -static void -ath5k_stop(struct ieee80211_hw *hw) -{ - ath5k_stop_hw(hw->priv); + ath5k_tx_queue(hw, skb, &ah->txqs[qnum]); } static int ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; int ret; struct ath5k_vif *avf = (void *)vif->drv_priv; - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); if ((vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) - && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) { + && (ah->num_ap_vifs + ah->num_adhoc_vifs) >= ATH_BCBUF) { ret = -ELNRNG; goto end; } @@ -100,9 +86,9 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) * We would need to operate the HW in ad-hoc mode to allow TSF updates * for the IBSS, but this breaks with additional AP or STA interfaces * at the moment. */ - if (sc->num_adhoc_vifs || - (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { - ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n"); + if (ah->num_adhoc_vifs || + (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { + ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n"); ret = -ELNRNG; goto end; } @@ -119,8 +105,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto end; } - sc->nvifs++; - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); + ah->nvifs++; + ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); /* Assign the vap/adhoc to a beacon xmit slot. */ if ((avf->opmode == NL80211_IFTYPE_AP) || @@ -128,38 +114,38 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { int slot; - WARN_ON(list_empty(&sc->bcbuf)); - avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf, + WARN_ON(list_empty(&ah->bcbuf)); + avf->bbuf = list_first_entry(&ah->bcbuf, struct ath5k_buf, list); list_del(&avf->bbuf->list); avf->bslot = 0; for (slot = 0; slot < ATH_BCBUF; slot++) { - if (!sc->bslot[slot]) { + if (!ah->bslot[slot]) { avf->bslot = slot; break; } } - BUG_ON(sc->bslot[avf->bslot] != NULL); - sc->bslot[avf->bslot] = vif; + BUG_ON(ah->bslot[avf->bslot] != NULL); + ah->bslot[avf->bslot] = vif; if (avf->opmode == NL80211_IFTYPE_AP) - sc->num_ap_vifs++; + ah->num_ap_vifs++; else if (avf->opmode == NL80211_IFTYPE_ADHOC) - sc->num_adhoc_vifs++; + ah->num_adhoc_vifs++; } /* Any MAC address is fine, all others are included through the * filter. */ - memcpy(&sc->lladdr, vif->addr, ETH_ALEN); - ath5k_hw_set_lladdr(sc->ah, vif->addr); + memcpy(&ah->lladdr, vif->addr, ETH_ALEN); + ath5k_hw_set_lladdr(ah, vif->addr); memcpy(&avf->lladdr, vif->addr, ETH_ALEN); - ath5k_update_bssid_mask_and_opmode(sc, vif); + ath5k_update_bssid_mask_and_opmode(ah, vif); ret = 0; end: - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); return ret; } @@ -168,31 +154,31 @@ static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; struct ath5k_vif *avf = (void *)vif->drv_priv; unsigned int i; - mutex_lock(&sc->lock); - sc->nvifs--; + mutex_lock(&ah->lock); + ah->nvifs--; if (avf->bbuf) { - ath5k_txbuf_free_skb(sc, avf->bbuf); - list_add_tail(&avf->bbuf->list, &sc->bcbuf); + ath5k_txbuf_free_skb(ah, avf->bbuf); + list_add_tail(&avf->bbuf->list, &ah->bcbuf); for (i = 0; i < ATH_BCBUF; i++) { - if (sc->bslot[i] == vif) { - sc->bslot[i] = NULL; + if (ah->bslot[i] == vif) { + ah->bslot[i] = NULL; break; } } avf->bbuf = NULL; } if (avf->opmode == NL80211_IFTYPE_AP) - sc->num_ap_vifs--; + ah->num_ap_vifs--; else if (avf->opmode == NL80211_IFTYPE_ADHOC) - sc->num_adhoc_vifs--; + ah->num_adhoc_vifs--; - ath5k_update_bssid_mask_and_opmode(sc, NULL); - mutex_unlock(&sc->lock); + ath5k_update_bssid_mask_and_opmode(ah, NULL); + mutex_unlock(&ah->lock); } @@ -202,23 +188,22 @@ ath5k_remove_interface(struct ieee80211_hw *hw, static int ath5k_config(struct ieee80211_hw *hw, u32 changed) { - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ieee80211_conf *conf = &hw->conf; int ret = 0; int i; - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ret = ath5k_chan_set(sc, conf->channel); + ret = ath5k_chan_set(ah, conf->channel); if (ret < 0) goto unlock; } if ((changed & IEEE80211_CONF_CHANGE_POWER) && - (sc->power_level != conf->power_level)) { - sc->power_level = conf->power_level; + (ah->power_level != conf->power_level)) { + ah->power_level = conf->power_level; /* Half dB steps */ ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); @@ -252,7 +237,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); unlock: - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); return ret; } @@ -262,12 +247,11 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes) { struct ath5k_vif *avf = (void *)vif->drv_priv; - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ath_common *common = ath5k_hw_common(ah); unsigned long flags; - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); if (changes & BSS_CHANGED_BSSID) { /* Cache for later use during resets */ @@ -278,7 +262,7 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changes & BSS_CHANGED_BEACON_INT) - sc->bintval = bss_conf->beacon_int; + ah->bintval = bss_conf->beacon_int; if (changes & BSS_CHANGED_ERP_SLOT) { int slot_time; @@ -292,16 +276,16 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_ASSOC) { avf->assoc = bss_conf->assoc; if (bss_conf->assoc) - sc->assoc = bss_conf->assoc; + ah->assoc = bss_conf->assoc; else - sc->assoc = ath5k_any_vif_assoc(sc); + ah->assoc = ath5k_any_vif_assoc(ah); - if (sc->opmode == NL80211_IFTYPE_STATION) - ath5k_set_beacon_filter(hw, sc->assoc); - ath5k_hw_set_ledstate(sc->ah, sc->assoc ? + if (ah->opmode == NL80211_IFTYPE_STATION) + ath5k_set_beacon_filter(hw, ah->assoc); + ath5k_hw_set_ledstate(ah, ah->assoc ? AR5K_LED_ASSOC : AR5K_LED_INIT); if (bss_conf->assoc) { - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, + ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "Bss Info ASSOC %d, bssid: %pM\n", bss_conf->aid, common->curbssid); common->curaid = bss_conf->aid; @@ -311,19 +295,19 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changes & BSS_CHANGED_BEACON) { - spin_lock_irqsave(&sc->block, flags); + spin_lock_irqsave(&ah->block, flags); ath5k_beacon_update(hw, vif); - spin_unlock_irqrestore(&sc->block, flags); + spin_unlock_irqrestore(&ah->block, flags); } if (changes & BSS_CHANGED_BEACON_ENABLED) - sc->enable_beacon = bss_conf->enable_beacon; + ah->enable_beacon = bss_conf->enable_beacon; if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) - ath5k_beacon_config(sc); + ath5k_beacon_config(ah); - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); } @@ -384,12 +368,11 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ FIF_BCN_PRBRESP_PROMISC) - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; u32 mfilt[2], rfilt; struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */ - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); mfilt[0] = multicast; mfilt[1] = multicast >> 32; @@ -407,12 +390,12 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { if (*new_flags & FIF_PROMISC_IN_BSS) - __set_bit(ATH_STAT_PROMISC, sc->status); + __set_bit(ATH_STAT_PROMISC, ah->status); else - __clear_bit(ATH_STAT_PROMISC, sc->status); + __clear_bit(ATH_STAT_PROMISC, ah->status); } - if (test_bit(ATH_STAT_PROMISC, sc->status)) + if (test_bit(ATH_STAT_PROMISC, ah->status)) rfilt |= AR5K_RX_FILTER_PROM; /* Note, AR5K_RX_FILTER_MCAST is already enabled */ @@ -427,7 +410,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons * and probes for any BSSID */ - if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1)) + if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (ah->nvifs > 1)) rfilt |= AR5K_RX_FILTER_BEACON; /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not @@ -442,7 +425,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ - switch (sc->opmode) { + switch (ah->opmode) { case NL80211_IFTYPE_MESH_POINT: rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | @@ -455,7 +438,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, AR5K_RX_FILTER_BEACON; break; case NL80211_IFTYPE_STATION: - if (sc->assoc) + if (ah->assoc) rfilt |= AR5K_RX_FILTER_BEACON; default: break; @@ -464,7 +447,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, iter_data.hw_macaddr = NULL; iter_data.n_stas = 0; iter_data.need_set_hw_addr = false; - ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, + ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter, &iter_data); /* Set up RX Filter */ @@ -483,9 +466,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); /* Set the cached hw filter flags, this will later actually * be set in HW */ - sc->filter_flags = rfilt; + ah->filter_flags = rfilt; - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); } @@ -494,8 +477,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ath_common *common = ath5k_hw_common(ah); int ret = 0; @@ -516,7 +498,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EINVAL; } - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); switch (cmd) { case SET_KEY: @@ -540,7 +522,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } mmiowb(); - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); return ret; } @@ -548,17 +530,17 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static void ath5k_sw_scan_start(struct ieee80211_hw *hw) { - struct ath5k_softc *sc = hw->priv; - if (!sc->assoc) - ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); + struct ath5k_hw *ah = hw->priv; + if (!ah->assoc) + ath5k_hw_set_ledstate(ah, AR5K_LED_SCAN); } static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) { - struct ath5k_softc *sc = hw->priv; - ath5k_hw_set_ledstate(sc->ah, sc->assoc ? + struct ath5k_hw *ah = hw->priv; + ath5k_hw_set_ledstate(ah, ah->assoc ? AR5K_LED_ASSOC : AR5K_LED_INIT); } @@ -567,15 +549,15 @@ static int ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; /* Force update */ - ath5k_hw_update_mib_counters(sc->ah); + ath5k_hw_update_mib_counters(ah); - stats->dot11ACKFailureCount = sc->stats.ack_fail; - stats->dot11RTSFailureCount = sc->stats.rts_fail; - stats->dot11RTSSuccessCount = sc->stats.rts_ok; - stats->dot11FCSErrorCount = sc->stats.fcs_error; + stats->dot11ACKFailureCount = ah->stats.ack_fail; + stats->dot11RTSFailureCount = ah->stats.rts_fail; + stats->dot11RTSSuccessCount = ah->stats.rts_ok; + stats->dot11FCSErrorCount = ah->stats.fcs_error; return 0; } @@ -585,15 +567,14 @@ static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; + struct ath5k_hw *ah = hw->priv; struct ath5k_txq_info qi; int ret = 0; if (queue >= ah->ah_capabilities.cap_queues.q_tx_num) return 0; - mutex_lock(&sc->lock); + mutex_lock(&ah->lock); ath5k_hw_get_tx_queueprops(ah, queue, &qi); @@ -602,20 +583,20 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, qi.tqi_cw_max = params->cw_max; qi.tqi_burst_time = params->txop; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, + ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "Configure tx [queue %d], " "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", queue, params->aifs, params->cw_min, params->cw_max, params->txop); if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) { - ATH5K_ERR(sc, + ATH5K_ERR(ah, "Unable to update hardware queue %u!\n", queue); ret = -EIO; } else ath5k_hw_reset_tx_queue(ah, queue); - mutex_unlock(&sc->lock); + mutex_unlock(&ah->lock); return ret; } @@ -624,43 +605,43 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, static u64 ath5k_get_tsf(struct ieee80211_hw *hw) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - return ath5k_hw_get_tsf64(sc->ah); + return ath5k_hw_get_tsf64(ah); } static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - ath5k_hw_set_tsf64(sc->ah, tsf); + ath5k_hw_set_tsf64(ah, tsf); } static void ath5k_reset_tsf(struct ieee80211_hw *hw) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; /* * in IBSS mode we need to update the beacon timers too. * this will also reset the TSF if we call it with 0 */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_beacon_update_timers(sc, 0); + if (ah->opmode == NL80211_IFTYPE_ADHOC) + ath5k_beacon_update_timers(ah, 0); else - ath5k_hw_reset_tsf(sc->ah); + ath5k_hw_reset_tsf(ah); } static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; struct ieee80211_conf *conf = &hw->conf; - struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_common *common = ath5k_hw_common(ah); struct ath_cycle_counters *cc = &common->cc_survey; unsigned int div = common->clockrate * 1000; @@ -670,18 +651,18 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) spin_lock_bh(&common->cc_lock); ath_hw_cycle_counters_update(common); if (cc->cycles > 0) { - sc->survey.channel_time += cc->cycles / div; - sc->survey.channel_time_busy += cc->rx_busy / div; - sc->survey.channel_time_rx += cc->rx_frame / div; - sc->survey.channel_time_tx += cc->tx_frame / div; + ah->survey.channel_time += cc->cycles / div; + ah->survey.channel_time_busy += cc->rx_busy / div; + ah->survey.channel_time_rx += cc->rx_frame / div; + ah->survey.channel_time_tx += cc->tx_frame / div; } memset(cc, 0, sizeof(*cc)); spin_unlock_bh(&common->cc_lock); - memcpy(survey, &sc->survey, sizeof(*survey)); + memcpy(survey, &ah->survey, sizeof(*survey)); survey->channel = conf->channel; - survey->noise = sc->ah->ah_noise_floor; + survey->noise = ah->ah_noise_floor; survey->filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY | @@ -705,25 +686,25 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - mutex_lock(&sc->lock); - ath5k_hw_set_coverage_class(sc->ah, coverage_class); - mutex_unlock(&sc->lock); + mutex_lock(&ah->lock); + ath5k_hw_set_coverage_class(ah, coverage_class); + mutex_unlock(&ah->lock); } static int ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; if (tx_ant == 1 && rx_ant == 1) - ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A); else if (tx_ant == 2 && rx_ant == 2) - ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B); else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) - ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); else return -EINVAL; return 0; @@ -733,9 +714,9 @@ ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) static int ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - switch (sc->ah->ah_ant_mode) { + switch (ah->ah_ant_mode) { case AR5K_ANTMODE_FIXED_A: *tx_ant = 1; *rx_ant = 1; break; case AR5K_ANTMODE_FIXED_B: @@ -750,9 +731,9 @@ ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) static void ath5k_get_ringparam(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - *tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max; + *tx = ah->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max; *tx_max = ATH5K_TXQ_LEN_MAX; *rx = *rx_max = ATH_RXBUF; @@ -761,7 +742,7 @@ static void ath5k_get_ringparam(struct ieee80211_hw *hw, static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx) { - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; u16 qnum; /* only support setting tx ring size for now */ @@ -772,16 +753,16 @@ static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx) if (!tx || tx > ATH5K_TXQ_LEN_MAX) return -EINVAL; - for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) { - if (!sc->txqs[qnum].setup) + for (qnum = 0; qnum < ARRAY_SIZE(ah->txqs); qnum++) { + if (!ah->txqs[qnum].setup) continue; - if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN || - sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX) + if (ah->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN || + ah->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX) continue; - sc->txqs[qnum].txq_max = tx; - if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max) - ieee80211_stop_queue(hw, sc->txqs[qnum].qnum); + ah->txqs[qnum].txq_max = tx; + if (ah->txqs[qnum].txq_len >= ah->txqs[qnum].txq_max) + ieee80211_stop_queue(hw, ah->txqs[qnum].qnum); } return 0; diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index aac5b78..eaf79b4 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -51,10 +51,10 @@ MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); /* return bus cachesize in 4B word units */ static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) { - struct ath5k_softc *sc = (struct ath5k_softc *) common->priv; + struct ath5k_hw *ah = (struct ath5k_hw *) common->priv; u8 u8tmp; - pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); + pci_read_config_byte(ah->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); *csz = (int)u8tmp; /* @@ -156,7 +156,7 @@ ath5k_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *mem; - struct ath5k_softc *sc; + struct ath5k_hw *ah; struct ieee80211_hw *hw; int ret; u8 csz; @@ -243,7 +243,7 @@ ath5k_pci_probe(struct pci_dev *pdev, * Allocate hw (mac80211 main struct) * and hw->priv (driver private data) */ - hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); + hw = ieee80211_alloc_hw(sizeof(*ah), &ath5k_hw_ops); if (hw == NULL) { dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); ret = -ENOMEM; @@ -252,16 +252,16 @@ ath5k_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); - sc = hw->priv; - sc->hw = hw; - sc->pdev = pdev; - sc->dev = &pdev->dev; - sc->irq = pdev->irq; - sc->devid = id->device; - sc->iobase = mem; /* So we can unmap it on detach */ + ah = hw->priv; + ah->hw = hw; + ah->pdev = pdev; + ah->dev = &pdev->dev; + ah->irq = pdev->irq; + ah->devid = id->device; + ah->iobase = mem; /* So we can unmap it on detach */ /* Initialize */ - ret = ath5k_init_softc(sc, &ath_pci_bus_ops); + ret = ath5k_init_softc(ah, &ath_pci_bus_ops); if (ret) goto err_free; @@ -285,10 +285,10 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - ath5k_deinit_softc(sc); - pci_iounmap(pdev, sc->iobase); + ath5k_deinit_softc(ah); + pci_iounmap(pdev, ah->iobase); pci_release_region(pdev, 0); pci_disable_device(pdev); ieee80211_free_hw(hw); @@ -299,9 +299,9 @@ static int ath5k_pci_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; - ath5k_led_off(sc); + ath5k_led_off(ah); return 0; } @@ -309,7 +309,7 @@ static int ath5k_pci_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = hw->priv; /* * Suspend/Resume resets the PCI configuration space, so we have to @@ -318,7 +318,7 @@ static int ath5k_pci_resume(struct device *dev) */ pci_write_config_byte(pdev, 0x41, 0); - ath5k_led_enable(sc); + ath5k_led_enable(ah); return 0; } diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 618ee54..0673138 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -77,14 +77,13 @@ static const unsigned int ack_rates_high[] = int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, int len, struct ieee80211_rate *rate, bool shortpre) { - struct ath5k_softc *sc = ah->ah_sc; int sifs, preamble, plcp_bits, sym_time; int bitrate, bits, symbols, symbol_bits; int dur; /* Fallback */ if (!ah->ah_bwmode) { - __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, + __le16 raw_dur = ieee80211_generic_frame_duration(ah->hw, NULL, len, rate); /* subtract difference between long and short preamble */ @@ -205,7 +204,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) */ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) { - struct ath5k_statistics *stats = &ah->ah_sc->stats; + struct ath5k_statistics *stats = &ah->stats; /* Read-And-Clear */ stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); @@ -240,25 +239,24 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) */ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) { - struct ath5k_softc *sc = ah->ah_sc; struct ieee80211_rate *rate; unsigned int i; /* 802.11g covers both OFDM and CCK */ u8 band = IEEE80211_BAND_2GHZ; /* Write rate duration table */ - for (i = 0; i < sc->sbands[band].n_bitrates; i++) { + for (i = 0; i < ah->sbands[band].n_bitrates; i++) { u32 reg; u16 tx_time; if (ah->ah_ack_bitrate_high) - rate = &sc->sbands[band].bitrates[ack_rates_high[i]]; + rate = &ah->sbands[band].bitrates[ack_rates_high[i]]; /* CCK -> 1Mb */ else if (i < 4) - rate = &sc->sbands[band].bitrates[0]; + rate = &ah->sbands[band].bitrates[0]; /* OFDM -> 6Mb */ else - rate = &sc->sbands[band].bitrates[4]; + rate = &ah->sbands[band].bitrates[4]; /* Set ACK timeout */ reg = AR5K_RATE_DUR(rate->hw_value); @@ -586,7 +584,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) /* * Set the additional timers by mode */ - switch (ah->ah_sc->opmode) { + switch (ah->opmode) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_STATION: /* In STA mode timer1 is used as next wakeup @@ -623,8 +621,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) * Set the beacon register and enable all timers. */ /* When in AP or Mesh Point mode zero timer0 to start TSF */ - if (ah->ah_sc->opmode == NL80211_IFTYPE_AP || - ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT) + if (ah->opmode == NL80211_IFTYPE_AP || + ah->opmode == NL80211_IFTYPE_MESH_POINT) ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); @@ -814,7 +812,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) struct ath_common *common = ath5k_hw_common(ah); u32 pcu_reg, beacon_reg, low_id, high_id; - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); + ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); /* Preserve rest settings */ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; @@ -890,7 +888,7 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * XXX: rethink this after new mode changes to * mac80211 are integrated */ if (ah->ah_version == AR5K_AR5212 && - ah->ah_sc->nvifs) + ah->nvifs) ath5k_hw_write_rate_duration(ah); /* Set RSSI/BRSSI thresholds diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index dd2b417..81e465e 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -22,6 +22,7 @@ #include <linux/delay.h> #include <linux/slab.h> +#include <asm/unaligned.h> #include "ath5k.h" #include "reg.h" @@ -561,7 +562,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) } done: - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "ret %d, gain step %u, current gain %u, target gain %u\n", ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current, ah->ah_gain.g_target); @@ -773,7 +774,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size, GFP_KERNEL); if (ah->ah_rf_banks == NULL) { - ATH5K_ERR(ah->ah_sc, "out of memory\n"); + ATH5K_ERR(ah, "out of memory\n"); return -ENOMEM; } } @@ -783,7 +784,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, for (i = 0; i < ah->ah_rf_banks_size; i++) { if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) { - ATH5K_ERR(ah->ah_sc, "invalid bank\n"); + ATH5K_ERR(ah, "invalid bank\n"); return -EINVAL; } @@ -1268,7 +1269,7 @@ static int ath5k_hw_channel(struct ath5k_hw *ah, * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok() * of the band by that */ if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "channel frequency (%u MHz) out of supported " "band range\n", channel->center_freq); @@ -1356,7 +1357,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) } } for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "cal %d:%d\n", i, sort[i]); } return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2]; @@ -1382,7 +1383,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) /* keep last value if calibration hasn't completed */ if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "NF did not complete in calibration window\n"); return; @@ -1395,7 +1396,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) threshold = ee->ee_noise_floor_thr[ee_mode]; if (nf > threshold) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "noise floor failure detected; " "read %d, threshold %d\n", nf, threshold); @@ -1432,7 +1433,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) ah->ah_noise_floor = nf; - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "noise floor calibrated: %d\n", nf); } @@ -1520,7 +1521,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT); if (ret) { - ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", + ATH5K_ERR(ah, "calibration timeout (%uMHz)\n", channel->center_freq); return ret; } @@ -1555,7 +1556,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE, "iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr); if (i_pwr && q_pwr) break; @@ -1581,7 +1582,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) q_coff = (i_pwr / q_coffd) - 128; q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE, "new I:%d Q:%d (i_coffd:%x q_coffd:%x)", i_coff, q_coff, i_coffd, q_coffd); @@ -1966,7 +1967,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) ee_mode = ath5k_eeprom_mode_from_channel(channel); if (ee_mode < 0) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "invalid channel: %d\n", channel->center_freq); return; } @@ -2794,12 +2795,8 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) * Write TX power values */ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { - ath5k_hw_reg_write(ah, - ((pdadc_out[4 * i + 0] & 0xff) << 0) | - ((pdadc_out[4 * i + 1] & 0xff) << 8) | - ((pdadc_out[4 * i + 2] & 0xff) << 16) | - ((pdadc_out[4 * i + 3] & 0xff) << 24), - AR5K_PHY_PDADC_TXPOWER(i)); + u32 val = get_unaligned_le32(&pdadc_out[4 * i]); + ath5k_hw_reg_write(ah, val, AR5K_PHY_PDADC_TXPOWER(i)); } } @@ -3122,13 +3119,13 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, int ret; if (txpower > AR5K_TUNE_MAX_TXPOWER) { - ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); + ATH5K_ERR(ah, "invalid tx power: %u\n", txpower); return -EINVAL; } ee_mode = ath5k_eeprom_mode_from_channel(channel); if (ee_mode < 0) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "invalid channel: %d\n", channel->center_freq); return -EINVAL; } @@ -3229,7 +3226,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, + ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER, "changing txpower to %d\n", txpower); return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); @@ -3440,7 +3437,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, * during ath5k_phy_calibrate) */ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", + ATH5K_ERR(ah, "gain calibration timeout (%uMHz)\n", channel->center_freq); } diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index b18c502..65f1039 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -187,7 +187,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, break; case AR5K_TX_QUEUE_XR_DATA: if (ah->ah_version != AR5K_AR5212) - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "XR data queues only supported in" " 5212!\n"); queue = AR5K_TX_QUEUE_ID_XR_DATA; @@ -510,7 +510,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) { struct ieee80211_channel *channel = ah->ah_current_channel; - struct ath5k_softc *sc = ah->ah_sc; struct ieee80211_rate *rate; u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); @@ -546,9 +545,9 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) * Also we have different lowest rate for 802.11a */ if (channel->hw_value & CHANNEL_5GHZ) - rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; + rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; else - rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; + rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); @@ -622,7 +621,7 @@ int ath5k_hw_init_queues(struct ath5k_hw *ah) for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { ret = ath5k_hw_reset_tx_queue(ah, i); if (ret) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "failed to reset TX queue #%d\n", i); return ret; } diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 9f9c2ad..0686c5d 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -390,7 +390,7 @@ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) u32 val = 0; /* ah->ah_mac_srev is not available at this point yet */ - if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) { + if (ah->devid >= AR5K_SREV_AR2315_R6) { reg = (u32 __iomem *) AR5K_AR2315_RESET; if (mask & AR5K_RESET_CTL_PCU) val |= AR5K_AR2315_RESET_WMAC; @@ -398,7 +398,7 @@ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) val |= AR5K_AR2315_RESET_BB_WARM; } else { reg = (u32 __iomem *) AR5K_AR5312_RESET; - if (to_platform_device(ah->ah_sc->dev)->id == 0) { + if (to_platform_device(ah->dev)->id == 0) { if (mask & AR5K_RESET_CTL_PCU) val |= AR5K_AR5312_RESET_WMAC0; if (mask & AR5K_RESET_CTL_BASEBAND) @@ -530,7 +530,7 @@ commit: */ int ath5k_hw_on_hold(struct ath5k_hw *ah) { - struct pci_dev *pdev = ah->ah_sc->pdev; + struct pci_dev *pdev = ah->pdev; u32 bus_flags; int ret; @@ -540,7 +540,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) /* Make sure device is awake */ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); + ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); return ret; } @@ -565,14 +565,14 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) } if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n"); + ATH5K_ERR(ah, "failed to put device on warm reset\n"); return -EIO; } /* ...wakeup again!*/ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n"); + ATH5K_ERR(ah, "failed to put device on hold\n"); return ret; } @@ -584,7 +584,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) */ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) { - struct pci_dev *pdev = ah->ah_sc->pdev; + struct pci_dev *pdev = ah->pdev; u32 turbo, mode, clock, bus_flags; int ret; @@ -596,7 +596,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) /* Wakeup the device */ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); + ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); return ret; } } @@ -626,14 +626,14 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) } if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); + ATH5K_ERR(ah, "failed to reset the MAC Chip\n"); return -EIO; } /* ...wakeup again!...*/ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); + ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); return ret; } @@ -646,7 +646,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ret = ath5k_hw_nic_reset(ah, 0); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); + ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n"); return -EIO; } @@ -687,7 +687,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) else mode |= AR5K_PHY_MODE_MOD_DYN; } else { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "invalid radio modulation mode\n"); return -EINVAL; } @@ -703,12 +703,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) if (flags & CHANNEL_OFDM) mode |= AR5K_PHY_MODE_MOD_OFDM; else { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "invalid radio modulation mode\n"); return -EINVAL; } } else { - ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); + ATH5K_ERR(ah, "invalid radio frequency mode\n"); return -EINVAL; } @@ -1076,7 +1076,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* RF Bus grant won't work if we have pending * frames */ if (ret && fast) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "DMA didn't stop, falling back to normal reset\n"); fast = 0; /* Non fatal, just continue with @@ -1091,7 +1091,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, case CHANNEL_G: if (ah->ah_version <= AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "G mode not available on 5210/5211"); return -EINVAL; } @@ -1101,7 +1101,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, case CHANNEL_B: if (ah->ah_version < AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "B mode not available on 5210"); return -EINVAL; } @@ -1110,14 +1110,14 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, break; case CHANNEL_XR: if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "XR mode not available on 5211"); return -EINVAL; } mode = AR5K_MODE_XR; break; default: - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "invalid channel: %d\n", channel->center_freq); return -EINVAL; } @@ -1129,13 +1129,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, if (fast) { ret = ath5k_hw_phy_init(ah, channel, mode, true); if (ret) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "fast chan change failed, falling back to normal reset\n"); /* Non fatal, can happen eg. * on mode change */ ret = 0; } else { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "fast chan change successful\n"); return 0; } @@ -1268,7 +1268,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, */ ret = ath5k_hw_phy_init(ah, channel, mode, false); if (ret) { - ATH5K_ERR(ah->ah_sc, + ATH5K_ERR(ah, "failed to initialize PHY (%i) !\n", ret); return ret; } diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c index 41a877b..945fc9f 100644 --- a/drivers/net/wireless/ath/ath5k/rfkill.c +++ b/drivers/net/wireless/ath/ath5k/rfkill.c @@ -36,86 +36,81 @@ #include "base.h" -static inline void ath5k_rfkill_disable(struct ath5k_softc *sc) +static inline void ath5k_rfkill_disable(struct ath5k_hw *ah) { - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", - sc->rf_kill.gpio, sc->rf_kill.polarity); - ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); - ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity); + ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", + ah->rf_kill.gpio, ah->rf_kill.polarity); + ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio); + ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity); } -static inline void ath5k_rfkill_enable(struct ath5k_softc *sc) +static inline void ath5k_rfkill_enable(struct ath5k_hw *ah) { - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", - sc->rf_kill.gpio, sc->rf_kill.polarity); - ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); - ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity); + ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", + ah->rf_kill.gpio, ah->rf_kill.polarity); + ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio); + ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity); } -static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable) +static inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable) { - struct ath5k_hw *ah = sc->ah; u32 curval; - ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio); - curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); - ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ? + ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio); + curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio); + ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ? !!curval : !curval); } static bool -ath5k_is_rfkill_set(struct ath5k_softc *sc) +ath5k_is_rfkill_set(struct ath5k_hw *ah) { /* configuring GPIO for input for some reason disables rfkill */ - /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/ - return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) == - sc->rf_kill.polarity; + /*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/ + return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) == + ah->rf_kill.polarity; } static void ath5k_tasklet_rfkill_toggle(unsigned long data) { - struct ath5k_softc *sc = (void *)data; + struct ath5k_hw *ah = (void *)data; bool blocked; - blocked = ath5k_is_rfkill_set(sc); - wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked); + blocked = ath5k_is_rfkill_set(ah); + wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked); } void ath5k_rfkill_hw_start(struct ath5k_hw *ah) { - struct ath5k_softc *sc = ah->ah_sc; - /* read rfkill GPIO configuration from EEPROM header */ - sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; - sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; + ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; + ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; - tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, - (unsigned long)sc); + tasklet_init(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, + (unsigned long)ah); - ath5k_rfkill_disable(sc); + ath5k_rfkill_disable(ah); /* enable interrupt for rfkill switch */ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) - ath5k_rfkill_set_intr(sc, true); + ath5k_rfkill_set_intr(ah, true); } void ath5k_rfkill_hw_stop(struct ath5k_hw *ah) { - struct ath5k_softc *sc = ah->ah_sc; - /* disable interrupt for rfkill switch */ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) - ath5k_rfkill_set_intr(sc, false); + ath5k_rfkill_set_intr(ah, false); - tasklet_kill(&sc->rf_kill.toggleq); + tasklet_kill(&ah->rf_kill.toggleq); /* enable RFKILL when stopping HW so Wifi LED is turned off */ - ath5k_rfkill_enable(sc); + ath5k_rfkill_enable(ah); } diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c index d8ad0e4..0244a36 100644 --- a/drivers/net/wireless/ath/ath5k/sysfs.c +++ b/drivers/net/wireless/ath/ath5k/sysfs.c @@ -11,7 +11,7 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \ char *buf) \ { \ struct ieee80211_hw *hw = dev_get_drvdata(dev); \ - struct ath5k_softc *sc = hw->priv; \ + struct ath5k_hw *ah = hw->priv; \ return snprintf(buf, PAGE_SIZE, "%d\n", get); \ } \ \ @@ -20,13 +20,13 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \ const char *buf, size_t count) \ { \ struct ieee80211_hw *hw = dev_get_drvdata(dev); \ - struct ath5k_softc *sc = hw->priv; \ + struct ath5k_hw *ah = hw->priv; \ int val, ret; \ \ ret = kstrtoint(buf, 10, &val); \ if (ret < 0) \ return ret; \ - set(sc->ah, val); \ + set(ah, val); \ return count; \ } \ static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \ @@ -38,25 +38,25 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \ char *buf) \ { \ struct ieee80211_hw *hw = dev_get_drvdata(dev); \ - struct ath5k_softc *sc = hw->priv; \ + struct ath5k_hw *ah = hw->priv; \ return snprintf(buf, PAGE_SIZE, "%d\n", get); \ } \ static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) /*** ANI ***/ -SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init); -SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level, +SIMPLE_SHOW_STORE(ani_mode, ah->ani_state.ani_mode, ath5k_ani_init); +SIMPLE_SHOW_STORE(noise_immunity_level, ah->ani_state.noise_imm_level, ath5k_ani_set_noise_immunity_level); -SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level, +SIMPLE_SHOW_STORE(spur_level, ah->ani_state.spur_level, ath5k_ani_set_spur_immunity_level); -SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level, +SIMPLE_SHOW_STORE(firstep_level, ah->ani_state.firstep_level, ath5k_ani_set_firstep_level); -SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig, +SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, ah->ani_state.ofdm_weak_sig, ath5k_ani_set_ofdm_weak_signal_detection); -SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig, +SIMPLE_SHOW_STORE(cck_weak_signal_detection, ah->ani_state.cck_weak_sig, ath5k_ani_set_cck_weak_signal_detection); -SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level); +SIMPLE_SHOW(spur_level_max, ah->ani_state.max_spur_level); static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev, struct device_attribute *attr, @@ -98,14 +98,14 @@ static struct attribute_group ath5k_attribute_group_ani = { /*** register / unregister ***/ int -ath5k_sysfs_register(struct ath5k_softc *sc) +ath5k_sysfs_register(struct ath5k_hw *ah) { - struct device *dev = sc->dev; + struct device *dev = ah->dev; int err; err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); if (err) { - ATH5K_ERR(sc, "failed to create sysfs group\n"); + ATH5K_ERR(ah, "failed to create sysfs group\n"); return err; } @@ -113,9 +113,9 @@ ath5k_sysfs_register(struct ath5k_softc *sc) } void -ath5k_sysfs_unregister(struct ath5k_softc *sc) +ath5k_sysfs_unregister(struct ath5k_hw *ah) { - struct device *dev = sc->dev; + struct device *dev = ah->dev; sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); } diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h index 235e076..c741c87 100644 --- a/drivers/net/wireless/ath/ath5k/trace.h +++ b/drivers/net/wireless/ath/ath5k/trace.h @@ -16,10 +16,10 @@ struct sk_buff; #define TRACE_SYSTEM ath5k TRACE_EVENT(ath5k_rx, - TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb), + TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb), TP_ARGS(priv, skb), TP_STRUCT__entry( - __field(struct ath5k_softc *, priv) + __field(struct ath5k_hw *, priv) __field(unsigned long, skbaddr) __dynamic_array(u8, frame, skb->len) ), @@ -34,13 +34,13 @@ TRACE_EVENT(ath5k_rx, ); TRACE_EVENT(ath5k_tx, - TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb, + TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb, struct ath5k_txq *q), TP_ARGS(priv, skb, q), TP_STRUCT__entry( - __field(struct ath5k_softc *, priv) + __field(struct ath5k_hw *, priv) __field(unsigned long, skbaddr) __field(u8, qnum) __dynamic_array(u8, frame, skb->len) @@ -60,13 +60,13 @@ TRACE_EVENT(ath5k_tx, ); TRACE_EVENT(ath5k_tx_complete, - TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb, + TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb, struct ath5k_txq *q, struct ath5k_tx_status *ts), TP_ARGS(priv, skb, q, ts), TP_STRUCT__entry( - __field(struct ath5k_softc *, priv) + __field(struct ath5k_hw *, priv) __field(unsigned long, skbaddr) __field(u8, qnum) __field(u8, ts_status) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 1d09f22..d109c25 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <asm/unaligned.h> #include "hw.h" #include "ar9003_phy.h" #include "ar9003_eeprom.h" @@ -3006,11 +3007,11 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, switch (param) { case EEP_MAC_LSW: - return eep->macAddr[0] << 8 | eep->macAddr[1]; + return get_unaligned_be16(eep->macAddr); case EEP_MAC_MID: - return eep->macAddr[2] << 8 | eep->macAddr[3]; + return get_unaligned_be16(eep->macAddr + 2); case EEP_MAC_MSW: - return eep->macAddr[4] << 8 | eep->macAddr[5]; + return get_unaligned_be16(eep->macAddr + 4); case EEP_REG_0: return le16_to_cpu(pBase->regDmn[0]); case EEP_REG_1: @@ -3038,7 +3039,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, case EEP_CHAIN_MASK_REDUCE: return (pBase->miscConfiguration >> 0x3) & 0x1; case EEP_ANT_DIV_CTL1: - return le32_to_cpu(eep->base_ext1.ant_div_control); + return eep->base_ext1.ant_div_control; default: return 0; } @@ -3380,8 +3381,7 @@ found: osize = length; read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN); checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); - mchecksum = word[COMP_HDR_LEN + osize] | - (word[COMP_HDR_LEN + osize + 1] << 8); + mchecksum = get_unaligned_le16(&word[COMP_HDR_LEN + osize]); ath_dbg(common, ATH_DBG_EEPROM, "checksum %x %x\n", checksum, mchecksum); if (checksum == mchecksum) { diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 41ce0b1..6635c37 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -50,7 +50,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) .bt_first_slot_time = 5, .bt_hold_rx_clear = true, }; - u32 i; + u32 i, idx; bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; if (AR_SREV_9300_20_OR_LATER(ah)) @@ -73,8 +73,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | AR_BT_DISABLE_BT_ANT; - for (i = 0; i < 32; i++) - ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; + for (i = 0; i < 32; i++) { + idx = (debruijn32 << i) >> 27; + ah->hw_gen_timers.gen_timer_index[idx] = i; + } } EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 22d3a26e..d1eb896 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -749,7 +749,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, char *buf; unsigned int len = 0, size = 8000; ssize_t retval = 0; - const char *tmp; unsigned int reg; struct ath9k_vif_iter_data iter_data; @@ -759,31 +758,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, if (buf == NULL) return -ENOMEM; - switch (sc->sc_ah->opmode) { - case NL80211_IFTYPE_ADHOC: - tmp = "ADHOC"; - break; - case NL80211_IFTYPE_MESH_POINT: - tmp = "MESH"; - break; - case NL80211_IFTYPE_AP: - tmp = "AP"; - break; - case NL80211_IFTYPE_STATION: - tmp = "STATION"; - break; - default: - tmp = "???"; - break; - } - ath9k_ps_wakeup(sc); len += snprintf(buf + len, size - len, "curbssid: %pM\n" "OP-Mode: %s(%i)\n" "Beacon-Timer-Register: 0x%x\n", common->curbssid, - tmp, (int)(sc->sc_ah->opmode), + ath_opmode_to_string(sc->sc_ah->opmode), + (int)(sc->sc_ah->opmode), REG_READ(ah, AR_BEACON_PERIOD)); reg = REG_READ(ah, AR_TIMER_MODE); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 5b1e894..47cc950 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <asm/unaligned.h> #include "hw.h" #include "ar9002_phy.h" @@ -203,11 +204,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, case EEP_NFTHRESH_2: return pModal->noiseFloorThreshCh[0]; case EEP_MAC_LSW: - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; + return get_unaligned_be16(pBase->macAddr); case EEP_MAC_MID: - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; + return get_unaligned_be16(pBase->macAddr + 2); case EEP_MAC_MSW: - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; + return get_unaligned_be16(pBase->macAddr + 4); case EEP_REG_0: return pBase->regDmn[0]; case EEP_REG_1: @@ -331,10 +332,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | - ((pdadcValues[4 * j + 1] & 0xFF) << 8) | - ((pdadcValues[4 * j + 2] & 0xFF) << 16)| - ((pdadcValues[4 * j + 3] & 0xFF) << 24); + reg32 = get_unaligned_le32(&pdadcValues[4 * j]); REG_WRITE(ah, regOffset, reg32); ath_dbg(common, ATH_DBG_EEPROM, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 343fc9f..d6f6b19 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <asm/unaligned.h> #include "hw.h" #include "ar9002_phy.h" @@ -195,11 +196,11 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, case EEP_NFTHRESH_2: return pModal->noiseFloorThreshCh[0]; case EEP_MAC_LSW: - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; + return get_unaligned_be16(pBase->macAddr); case EEP_MAC_MID: - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; + return get_unaligned_be16(pBase->macAddr + 2); case EEP_MAC_MSW: - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; + return get_unaligned_be16(pBase->macAddr + 4); case EEP_REG_0: return pBase->regDmn[0]; case EEP_REG_1: @@ -434,10 +435,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, (672 << 2) + regChainOffset; for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) - | ((pdadcValues[4*j + 1] & 0xFF) << 8) - | ((pdadcValues[4*j + 2] & 0xFF) << 16) - | ((pdadcValues[4*j + 3] & 0xFF) << 24); + reg32 = get_unaligned_le32(&pdadcValues[4 * j]); REG_WRITE(ah, regOffset, reg32); regOffset += 4; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 17f0a68..b9540a9 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <asm/unaligned.h> #include "hw.h" #include "ar9002_phy.h" @@ -276,11 +277,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, case EEP_NFTHRESH_2: return pModal[1].noiseFloorThreshCh[0]; case EEP_MAC_LSW: - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; + return get_unaligned_be16(pBase->macAddr); case EEP_MAC_MID: - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; + return get_unaligned_be16(pBase->macAddr + 2); case EEP_MAC_MSW: - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; + return get_unaligned_be16(pBase->macAddr + 4); case EEP_REG_0: return pBase->regDmn[0]; case EEP_REG_1: @@ -831,10 +832,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | - ((pdadcValues[4 * j + 1] & 0xFF) << 8) | - ((pdadcValues[4 * j + 2] & 0xFF) << 16)| - ((pdadcValues[4 * j + 3] & 0xFF) << 24); + reg32 = get_unaligned_le32(&pdadcValues[4 * j]); REG_WRITE(ah, regOffset, reg32); ath_dbg(common, ATH_DBG_EEPROM, diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 8028fe9..d3f4a59c 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <asm/unaligned.h> #include "htc.h" /* identify firmware images */ @@ -129,12 +130,14 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, static void hif_usb_mgmt_cb(struct urb *urb) { struct cmd_buf *cmd = (struct cmd_buf *)urb->context; - struct hif_device_usb *hif_dev = cmd->hif_dev; + struct hif_device_usb *hif_dev; bool txok = true; if (!cmd || !cmd->skb || !cmd->hif_dev) return; + hif_dev = cmd->hif_dev; + switch (urb->status) { case 0: break; @@ -557,8 +560,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, ptr = (u8 *) skb->data; - pkt_len = ptr[index] + (ptr[index+1] << 8); - pkt_tag = ptr[index+2] + (ptr[index+3] << 8); + pkt_len = get_unaligned_le16(ptr + index); + pkt_tag = get_unaligned_le16(ptr + index + 2); if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { RX_STAT_INC(skb_dropped); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index aa48b3ab..d3ff33c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -623,11 +623,8 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, pBase9287->openLoopPwrCntl); } - len += snprintf(buf + len, size - len, - "%20s : %02X:%02X:%02X:%02X:%02X:%02X\n", - "MacAddress", - pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2], - pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]); + len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", + pBase->macAddr); if (len > size) len = size; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2a5f908..8006ce0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1997,12 +1997,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers); /* HW Capabilities */ /*******************/ +static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask) +{ + eeprom_chainmask &= chip_chainmask; + if (eeprom_chainmask) + return eeprom_chainmask; + else + return chip_chainmask; +} + int ath9k_hw_fill_cap_info(struct ath_hw *ah) { struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; + unsigned int chip_chainmask; u16 eeval; u8 ant_div_ctl1, tx_chainmask, rx_chainmask; @@ -2039,6 +2049,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (eeval & AR5416_OPFLAGS_11G) pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; + if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah)) + chip_chainmask = 1; + else if (!AR_SREV_9280_20_OR_LATER(ah)) + chip_chainmask = 7; + else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) + chip_chainmask = 3; + else + chip_chainmask = 7; + pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); /* * For AR9271 we will temporarilly uses the rx chainmax as read from @@ -2055,6 +2074,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); + pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); + pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); + ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; /* enable key search for every frame in an aggregate */ diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b855fe1..ac51071 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -197,6 +197,19 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) return val; } +static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset, + u32 set, u32 clr) +{ + u32 val; + + val = ioread32(sc->mem + reg_offset); + val &= ~clr; + val |= set; + iowrite32(val, sc->mem + reg_offset); + + return val; +} + static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) { struct ath_hw *ah = (struct ath_hw *) hw_priv; @@ -205,16 +218,12 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl unsigned long uninitialized_var(flags); u32 val; - if (ah->config.serialize_regmode == SER_REG_MODE_ON) + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { spin_lock_irqsave(&sc->sc_serial_rw, flags); - - val = ioread32(sc->mem + reg_offset); - val &= ~clr; - val |= set; - iowrite32(val, sc->mem + reg_offset); - - if (ah->config.serialize_regmode == SER_REG_MODE_ON) + val = __ath9k_reg_rmw(sc, reg_offset, set, clr); spin_unlock_irqrestore(&sc->sc_serial_rw, flags); + } else + val = __ath9k_reg_rmw(sc, reg_offset, set, clr); return val; } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 70dc8ec..9a48501 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -815,16 +815,19 @@ static bool ath9k_rx_accept(struct ath_common *common, struct ath_rx_status *rx_stats, bool *decrypt_error) { -#define is_mc_or_valid_tkip_keyix ((is_mc || \ - (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \ - test_bit(rx_stats->rs_keyix, common->tkip_keymap)))) - + bool is_mc, is_valid_tkip, strip_mic, mic_error; struct ath_hw *ah = common->ah; __le16 fc; u8 rx_status_len = ah->caps.rx_status_len; fc = hdr->frame_control; + is_mc = !!is_multicast_ether_addr(hdr->addr1); + is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && + test_bit(rx_stats->rs_keyix, common->tkip_keymap); + strip_mic = is_valid_tkip && !(rx_stats->rs_status & + (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC)); + if (!rx_stats->rs_datalen) return false; /* @@ -839,6 +842,11 @@ static bool ath9k_rx_accept(struct ath_common *common, if (rx_stats->rs_more) return true; + mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && + !ieee80211_has_morefrags(fc) && + !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && + (rx_stats->rs_status & ATH9K_RXERR_MIC); + /* * The rx_stats->rs_status will not be set until the end of the * chained descriptors so it can be ignored if rs_more is set. The @@ -846,30 +854,18 @@ static bool ath9k_rx_accept(struct ath_common *common, * descriptors. */ if (rx_stats->rs_status != 0) { - if (rx_stats->rs_status & ATH9K_RXERR_CRC) + if (rx_stats->rs_status & ATH9K_RXERR_CRC) { rxs->flag |= RX_FLAG_FAILED_FCS_CRC; + mic_error = false; + } if (rx_stats->rs_status & ATH9K_RXERR_PHY) return false; if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { *decrypt_error = true; - } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { - bool is_mc; - /* - * The MIC error bit is only valid if the frame - * is not a control frame or fragment, and it was - * decrypted using a valid TKIP key. - */ - is_mc = !!is_multicast_ether_addr(hdr->addr1); - - if (!ieee80211_is_ctl(fc) && - !ieee80211_has_morefrags(fc) && - !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && - is_mc_or_valid_tkip_keyix) - rxs->flag |= RX_FLAG_MMIC_ERROR; - else - rx_stats->rs_status &= ~ATH9K_RXERR_MIC; + mic_error = false; } + /* * Reject error frames with the exception of * decryption and MIC failures. For monitor mode, @@ -887,6 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common, } } } + + /* + * For unicast frames the MIC error bit can have false positives, + * so all MIC error reports need to be validated in software. + * False negatives are not common, so skip software verification + * if the hardware considers the MIC valid. + */ + if (strip_mic) + rxs->flag |= RX_FLAG_MMIC_STRIPPED; + else if (is_mc && mic_error) + rxs->flag |= RX_FLAG_MMIC_ERROR; + return true; } @@ -1939,6 +1947,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) sc->rx.rxotherant = 0; } + if (rxs->flag & RX_FLAG_MMIC_STRIPPED) + skb_trim(skb, skb->len - 8); + spin_lock_irqsave(&sc->sc_pm_lock, flags); if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 759b72c..fa4c0bb 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1873,29 +1873,6 @@ enum { #define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2)) -#define AR_KEYTABLE_0 0x8800 -#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) -#define AR_KEY_CACHE_SIZE 128 -#define AR_RSVD_KEYTABLE_ENTRIES 4 -#define AR_KEY_TYPE 0x00000007 -#define AR_KEYTABLE_TYPE_40 0x00000000 -#define AR_KEYTABLE_TYPE_104 0x00000001 -#define AR_KEYTABLE_TYPE_128 0x00000003 -#define AR_KEYTABLE_TYPE_TKIP 0x00000004 -#define AR_KEYTABLE_TYPE_AES 0x00000005 -#define AR_KEYTABLE_TYPE_CCM 0x00000006 -#define AR_KEYTABLE_TYPE_CLR 0x00000007 -#define AR_KEYTABLE_ANT 0x00000008 -#define AR_KEYTABLE_VALID 0x00008000 -#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) -#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) -#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) -#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) -#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) -#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) -#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) -#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) - #define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ #define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 6eb58b1..cc59571 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1148,6 +1148,8 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, struct list_head *list, bool retry_tx) + __releases(txq->axq_lock) + __acquires(txq->axq_lock) { struct ath_buf *bf, *lastbf; struct list_head bf_head; @@ -2036,6 +2038,8 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf, struct list_head *bf_head) + __releases(txq->axq_lock) + __acquires(txq->axq_lock) { int txok; diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index f9a4655..c5427a7 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -177,7 +177,7 @@ struct carl9170_tx_queue_stats { struct carl9170_vif { unsigned int id; - struct ieee80211_vif *vif; + struct ieee80211_vif __rcu *vif; }; struct carl9170_vif_info { @@ -311,7 +311,7 @@ struct ar9170 { spinlock_t beacon_lock; unsigned int global_pretbtt; unsigned int global_beacon_int; - struct carl9170_vif_info *beacon_iter; + struct carl9170_vif_info __rcu *beacon_iter; unsigned int beacon_enabled; /* cryptographic engine */ @@ -389,7 +389,7 @@ struct ar9170 { /* tx ampdu */ struct work_struct ampdu_work; spinlock_t tx_ampdu_list_lock; - struct carl9170_sta_tid *tx_ampdu_iter; + struct carl9170_sta_tid __rcu *tx_ampdu_iter; struct list_head tx_ampdu_list; atomic_t tx_ampdu_upload; atomic_t tx_ampdu_scheduler; @@ -456,7 +456,7 @@ struct carl9170_sta_info { bool sleeping; atomic_t pending_frames; unsigned int ampdu_max_len; - struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; + struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID]; struct carl9170_ba_stats stats[CARL9170_NUM_TID]; }; @@ -532,7 +532,6 @@ int carl9170_set_ampdu_settings(struct ar9170 *ar); int carl9170_set_slot_time(struct ar9170 *ar); int carl9170_set_mac_rates(struct ar9170 *ar); int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry); -int carl9170_update_beacon(struct ar9170 *ar, const bool submit); int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen); int carl9170_disable_key(struct ar9170 *ar, const u8 id); @@ -553,6 +552,7 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb); void carl9170_tx_scheduler(struct ar9170 *ar); void carl9170_tx_get_skb(struct sk_buff *skb); int carl9170_tx_put_skb(struct sk_buff *skb); +int carl9170_update_beacon(struct ar9170 *ar, const bool submit); /* LEDs */ #ifdef CONFIG_CARL9170_LEDS diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h index 568174c..d5f95bd 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.h +++ b/drivers/net/wireless/ath/carl9170/cmd.h @@ -87,7 +87,7 @@ do { \ __ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \ __ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \ __nreg++; \ - if ((__nreg >= PAYLOAD_MAX/2)) { \ + if ((__nreg >= PAYLOAD_MAX / 2)) { \ if (IS_ACCEPTING_CMD(__ar)) \ __err = carl9170_exec_cmd(__ar, \ CARL9170_CMD_WREG, 8 * __nreg, \ @@ -160,7 +160,7 @@ do { \ } while (0) #define carl9170_async_regwrite_finish() do { \ -__async_regwrite_out : \ +__async_regwrite_out: \ if (__cmd != NULL && __err == 0) \ carl9170_async_regwrite_flush(); \ kfree(__cmd); \ diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 0ac1124..de57f90 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c @@ -695,7 +695,7 @@ static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf, } __DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED); -static const char *erp_modes[] = { +static const char *const erp_modes[] = { [CARL9170_ERP_INVALID] = "INVALID", [CARL9170_ERP_AUTO] = "Automatic", [CARL9170_ERP_MAC80211] = "Set by MAC80211", diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h index 7ba62bb..6d9c089 100644 --- a/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h @@ -75,6 +75,9 @@ enum carl9170fw_feature_list { /* Firmware supports PSM in the 5GHZ Band */ CARL9170FW_FIXED_5GHZ_PSM, + /* HW (ANI, CCA, MIB) tally counters */ + CARL9170FW_HW_COUNTERS, + /* KEEP LAST */ __CARL9170FW_FEATURE_NUM }; diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index 261f893..fa834c1 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h @@ -174,6 +174,7 @@ #define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0) #define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000 #define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) +#define AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE BIT(2) #define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3) #define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70 @@ -222,6 +223,12 @@ #define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0) #define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4) #define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8) +#define AR9170_MAC_BACKOFF_CCA BIT(24) +#define AR9170_MAC_BACKOFF_TX_PEX BIT(25) +#define AR9170_MAC_BACKOFF_RX_PE BIT(26) +#define AR9170_MAC_BACKOFF_MD_READY BIT(27) +#define AR9170_MAC_BACKOFF_TX_PE BIT(28) + #define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc) #define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4) @@ -388,10 +395,40 @@ #define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98) #define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c) - - #define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0) +#define AR9170_MAC_BCN_HT1_HT_EN BIT(0) +#define AR9170_MAC_BCN_HT1_GF_PMB BIT(1) +#define AR9170_MAC_BCN_HT1_SP_EXP BIT(2) +#define AR9170_MAC_BCN_HT1_TX_BF BIT(3) +#define AR9170_MAC_BCN_HT1_PWR_CTRL_S 4 +#define AR9170_MAC_BCN_HT1_PWR_CTRL 0x70 +#define AR9170_MAC_BCN_HT1_TX_ANT1 BIT(7) +#define AR9170_MAC_BCN_HT1_TX_ANT0 BIT(8) +#define AR9170_MAC_BCN_HT1_NUM_LFT_S 9 +#define AR9170_MAC_BCN_HT1_NUM_LFT 0x600 +#define AR9170_MAC_BCN_HT1_BWC_20M_EXT BIT(16) +#define AR9170_MAC_BCN_HT1_BWC_40M_SHARED BIT(17) +#define AR9170_MAC_BCN_HT1_BWC_40M_DUP (BIT(16) | BIT(17)) +#define AR9170_MAC_BCN_HT1_BF_MCS_S 18 +#define AR9170_MAC_BCN_HT1_BF_MCS 0x1c0000 +#define AR9170_MAC_BCN_HT1_TPC_S 21 +#define AR9170_MAC_BCN_HT1_TPC 0x7e00000 +#define AR9170_MAC_BCN_HT1_CHAIN_MASK_S 27 +#define AR9170_MAC_BCN_HT1_CHAIN_MASK 0x38000000 + #define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4) +#define AR9170_MAC_BCN_HT2_MCS_S 0 +#define AR9170_MAC_BCN_HT2_MCS 0x7f +#define AR9170_MAC_BCN_HT2_BW40 BIT(8) +#define AR9170_MAC_BCN_HT2_SMOOTHING BIT(9) +#define AR9170_MAC_BCN_HT2_SS BIT(10) +#define AR9170_MAC_BCN_HT2_NSS BIT(11) +#define AR9170_MAC_BCN_HT2_STBC_S 12 +#define AR9170_MAC_BCN_HT2_STBC 0x3000 +#define AR9170_MAC_BCN_HT2_ADV_COD BIT(14) +#define AR9170_MAC_BCN_HT2_SGI BIT(15) +#define AR9170_MAC_BCN_HT2_LEN_S 16 +#define AR9170_MAC_BCN_HT2_LEN 0xffff0000 #define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0) diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c index 4bb2cbd..78dadc7 100644 --- a/drivers/net/wireless/ath/carl9170/led.c +++ b/drivers/net/wireless/ath/carl9170/led.c @@ -118,7 +118,7 @@ static void carl9170_led_set_brightness(struct led_classdev *led, } if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) - ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); + ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10); } static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name, diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index 385cf50..dfda919 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c @@ -455,135 +455,6 @@ int carl9170_set_beacon_timers(struct ar9170 *ar) return carl9170_regwrite_result(); } -int carl9170_update_beacon(struct ar9170 *ar, const bool submit) -{ - struct sk_buff *skb = NULL; - struct carl9170_vif_info *cvif; - struct ieee80211_tx_info *txinfo; - __le32 *data, *old = NULL; - u32 word, off, addr, len; - int i = 0, err = 0; - - rcu_read_lock(); - cvif = rcu_dereference(ar->beacon_iter); -retry: - if (ar->vifs == 0 || !cvif) - goto out_unlock; - - list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) { - if (cvif->active && cvif->enable_beacon) - goto found; - } - - if (!ar->beacon_enabled || i++) - goto out_unlock; - - goto retry; - -found: - rcu_assign_pointer(ar->beacon_iter, cvif); - - skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), - NULL, NULL); - - if (!skb) { - err = -ENOMEM; - goto err_free; - } - - txinfo = IEEE80211_SKB_CB(skb); - if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) { - err = -EINVAL; - goto err_free; - } - - spin_lock_bh(&ar->beacon_lock); - data = (__le32 *)skb->data; - if (cvif->beacon) - old = (__le32 *)cvif->beacon->data; - - off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX; - addr = ar->fw.beacon_addr + off; - len = roundup(skb->len + FCS_LEN, 4); - - if ((off + len) > ar->fw.beacon_max_len) { - if (net_ratelimit()) { - wiphy_err(ar->hw->wiphy, "beacon does not " - "fit into device memory!\n"); - } - err = -EINVAL; - goto err_unlock; - } - - if (len > AR9170_MAC_BCN_LENGTH_MAX) { - if (net_ratelimit()) { - wiphy_err(ar->hw->wiphy, "no support for beacons " - "bigger than %d (yours:%d).\n", - AR9170_MAC_BCN_LENGTH_MAX, len); - } - - err = -EMSGSIZE; - goto err_unlock; - } - - i = txinfo->control.rates[0].idx; - if (txinfo->band != IEEE80211_BAND_2GHZ) - i += 4; - - word = __carl9170_ratetable[i].hw_value & 0xf; - if (i < 4) - word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; - else - word |= ((skb->len + FCS_LEN) << 16) + 0x0010; - - carl9170_async_regwrite_begin(ar); - carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word); - - for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { - /* - * XXX: This accesses beyond skb data for up - * to the last 3 bytes!! - */ - - if (old && (data[i] == old[i])) - continue; - - word = le32_to_cpu(data[i]); - carl9170_async_regwrite(addr + 4 * i, word); - } - carl9170_async_regwrite_finish(); - - dev_kfree_skb_any(cvif->beacon); - cvif->beacon = NULL; - - err = carl9170_async_regwrite_result(); - if (!err) - cvif->beacon = skb; - spin_unlock_bh(&ar->beacon_lock); - if (err) - goto err_free; - - if (submit) { - err = carl9170_bcn_ctrl(ar, cvif->id, - CARL9170_BCN_CTRL_CAB_TRIGGER, - addr, skb->len + FCS_LEN); - - if (err) - goto err_free; - } -out_unlock: - rcu_read_unlock(); - return 0; - -err_unlock: - spin_unlock_bh(&ar->beacon_lock); - -err_free: - rcu_read_unlock(); - dev_kfree_skb_any(skb); - return err; -} - int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen) diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index a61cf67..0122930 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1630,7 +1630,7 @@ static int carl9170_read_eeprom(struct ar9170 *ar) BUILD_BUG_ON(sizeof(ar->eeprom) % RB); #endif - for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { + for (i = 0; i < sizeof(ar->eeprom) / RB; i++) { for (j = 0; j < RW; j++) offsets[j] = cpu_to_le32(AR9170_EEPROM_START + RB * i + 4 * j); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index da1ab96..aa147a9 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -1098,7 +1098,7 @@ static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) * Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)? * Can we rely on the compiler to optimise away the div? */ - return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); + return (y >> SHIFT) + ((y & (1 << (SHIFT - 1))) >> (SHIFT - 1)); #undef SHIFT } @@ -1379,7 +1379,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) modes[i].max_power = carl9170_get_max_edge_power(ar, - freq+f_off, EDGES(ctl_idx, 1)); + freq + f_off, EDGES(ctl_idx, 1)); /* * TODO: check if the regulatory max. power is @@ -1441,7 +1441,7 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, if (freq < 3000) f = freq - 2300; else - f = (freq - 4800)/5; + f = (freq - 4800) / 5; /* * cycle through the various modes diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index e94084f..d209469 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -661,11 +661,67 @@ void carl9170_tx_process_status(struct ar9170 *ar, } } +static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar, + struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate, + unsigned int *phyrate, unsigned int *tpc, unsigned int *chains) +{ + struct ieee80211_rate *rate = NULL; + u8 *txpower; + unsigned int idx; + + idx = txrate->idx; + *tpc = 0; + *phyrate = 0; + + if (txrate->flags & IEEE80211_TX_RC_MCS) { + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { + /* +1 dBm for HT40 */ + *tpc += 2; + + if (info->band == IEEE80211_BAND_2GHZ) + txpower = ar->power_2G_ht40; + else + txpower = ar->power_5G_ht40; + } else { + if (info->band == IEEE80211_BAND_2GHZ) + txpower = ar->power_2G_ht20; + else + txpower = ar->power_5G_ht20; + } + + *phyrate = txrate->idx; + *tpc += txpower[idx & 7]; + } else { + if (info->band == IEEE80211_BAND_2GHZ) { + if (idx < 4) + txpower = ar->power_2G_cck; + else + txpower = ar->power_2G_ofdm; + } else { + txpower = ar->power_5G_leg; + idx += 4; + } + + rate = &__carl9170_ratetable[idx]; + *tpc += txpower[(rate->hw_value & 0x30) >> 4]; + *phyrate = rate->hw_value & 0xf; + } + + if (ar->eeprom.tx_mask == 1) { + *chains = AR9170_TX_PHY_TXCHAIN_1; + } else { + if (!(txrate->flags & IEEE80211_TX_RC_MCS) && + rate && rate->bitrate >= 360) + *chains = AR9170_TX_PHY_TXCHAIN_1; + else + *chains = AR9170_TX_PHY_TXCHAIN_2; + } +} + static __le32 carl9170_tx_physet(struct ar9170 *ar, struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate) { - struct ieee80211_rate *rate = NULL; - u32 power, chains; + unsigned int power = 0, chains = 0, phyrate = 0; __le32 tmp; tmp = cpu_to_le32(0); @@ -682,35 +738,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar, tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); if (txrate->flags & IEEE80211_TX_RC_MCS) { - u32 r = txrate->idx; - u8 *txpower; + SET_VAL(AR9170_TX_PHY_MCS, phyrate, txrate->idx); /* heavy clip control */ - tmp |= cpu_to_le32((r & 0x7) << + tmp |= cpu_to_le32((txrate->idx & 0x7) << AR9170_TX_PHY_TX_HEAVY_CLIP_S); - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht40; - else - txpower = ar->power_2G_ht40; - } else { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht20; - else - txpower = ar->power_2G_ht20; - } - - power = txpower[r & 7]; - - /* +1 dBm for HT40 */ - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - power += 2; - - r <<= AR9170_TX_PHY_MCS_S; - BUG_ON(r & ~AR9170_TX_PHY_MCS); - - tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS); tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); /* @@ -720,34 +753,15 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar, * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); */ } else { - u8 *txpower; - u32 mod; - u32 phyrate; - u8 idx = txrate->idx; - - if (info->band != IEEE80211_BAND_2GHZ) { - idx += 4; - txpower = ar->power_5G_leg; - mod = AR9170_TX_PHY_MOD_OFDM; + if (info->band == IEEE80211_BAND_2GHZ) { + if (txrate->idx <= AR9170_TX_PHY_RATE_CCK_11M) + tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_CCK); + else + tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM); } else { - if (idx < 4) { - txpower = ar->power_2G_cck; - mod = AR9170_TX_PHY_MOD_CCK; - } else { - mod = AR9170_TX_PHY_MOD_OFDM; - txpower = ar->power_2G_ofdm; - } + tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM); } - rate = &__carl9170_ratetable[idx]; - - phyrate = rate->hw_value & 0xF; - power = txpower[(rate->hw_value & 0x30) >> 4]; - phyrate <<= AR9170_TX_PHY_MCS_S; - - tmp |= cpu_to_le32(mod); - tmp |= cpu_to_le32(phyrate); - /* * short preamble seems to be broken too. * @@ -755,23 +769,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar, * tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); */ } - power <<= AR9170_TX_PHY_TX_PWR_S; - power &= AR9170_TX_PHY_TX_PWR; - tmp |= cpu_to_le32(power); - - /* set TX chains */ - if (ar->eeprom.tx_mask == 1) { - chains = AR9170_TX_PHY_TXCHAIN_1; - } else { - chains = AR9170_TX_PHY_TXCHAIN_2; - - /* >= 36M legacy OFDM - use only one chain */ - if (rate && rate->bitrate >= 360 && - !(txrate->flags & IEEE80211_TX_RC_MCS)) - chains = AR9170_TX_PHY_TXCHAIN_1; - } - tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S); + carl9170_tx_rate_tpc_chains(ar, info, txrate, + &phyrate, &power, &chains); + tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_MCS, phyrate)); + tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TX_PWR, power)); + tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TXCHAIN, chains)); return tmp; } @@ -1438,3 +1441,154 @@ void carl9170_tx_scheduler(struct ar9170 *ar) if (ar->tx_schedule) carl9170_tx(ar); } + +int carl9170_update_beacon(struct ar9170 *ar, const bool submit) +{ + struct sk_buff *skb = NULL; + struct carl9170_vif_info *cvif; + struct ieee80211_tx_info *txinfo; + struct ieee80211_tx_rate *rate; + __le32 *data, *old = NULL; + unsigned int plcp, power, chains; + u32 word, ht1, off, addr, len; + int i = 0, err = 0; + + rcu_read_lock(); + cvif = rcu_dereference(ar->beacon_iter); +retry: + if (ar->vifs == 0 || !cvif) + goto out_unlock; + + list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) { + if (cvif->active && cvif->enable_beacon) + goto found; + } + + if (!ar->beacon_enabled || i++) + goto out_unlock; + + goto retry; + +found: + rcu_assign_pointer(ar->beacon_iter, cvif); + + skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), + NULL, NULL); + + if (!skb) { + err = -ENOMEM; + goto err_free; + } + + txinfo = IEEE80211_SKB_CB(skb); + spin_lock_bh(&ar->beacon_lock); + data = (__le32 *)skb->data; + if (cvif->beacon) + old = (__le32 *)cvif->beacon->data; + + off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX; + addr = ar->fw.beacon_addr + off; + len = roundup(skb->len + FCS_LEN, 4); + + if ((off + len) > ar->fw.beacon_max_len) { + if (net_ratelimit()) { + wiphy_err(ar->hw->wiphy, "beacon does not " + "fit into device memory!\n"); + } + err = -EINVAL; + goto err_unlock; + } + + if (len > AR9170_MAC_BCN_LENGTH_MAX) { + if (net_ratelimit()) { + wiphy_err(ar->hw->wiphy, "no support for beacons " + "bigger than %d (yours:%d).\n", + AR9170_MAC_BCN_LENGTH_MAX, len); + } + + err = -EMSGSIZE; + goto err_unlock; + } + + ht1 = AR9170_MAC_BCN_HT1_TX_ANT0; + rate = &txinfo->control.rates[0]; + carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains); + if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) { + if (plcp <= AR9170_TX_PHY_RATE_CCK_11M) + plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; + else + plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010; + } else { + ht1 |= AR9170_MAC_BCN_HT1_HT_EN; + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + plcp |= AR9170_MAC_BCN_HT2_SGI; + + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { + ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED; + plcp |= AR9170_MAC_BCN_HT2_BW40; + } + if (rate->flags & IEEE80211_TX_RC_DUP_DATA) { + ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP; + plcp |= AR9170_MAC_BCN_HT2_BW40; + } + + SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN); + } + + SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7); + SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power); + SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains); + if (chains == AR9170_TX_PHY_TXCHAIN_2) + ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1; + + carl9170_async_regwrite_begin(ar); + carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1); + if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) + carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp); + else + carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp); + + for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { + /* + * XXX: This accesses beyond skb data for up + * to the last 3 bytes!! + */ + + if (old && (data[i] == old[i])) + continue; + + word = le32_to_cpu(data[i]); + carl9170_async_regwrite(addr + 4 * i, word); + } + carl9170_async_regwrite_finish(); + + dev_kfree_skb_any(cvif->beacon); + cvif->beacon = NULL; + + err = carl9170_async_regwrite_result(); + if (!err) + cvif->beacon = skb; + spin_unlock_bh(&ar->beacon_lock); + if (err) + goto err_free; + + if (submit) { + err = carl9170_bcn_ctrl(ar, cvif->id, + CARL9170_BCN_CTRL_CAB_TRIGGER, + addr, skb->len + FCS_LEN); + + if (err) + goto err_free; + } +out_unlock: + rcu_read_unlock(); + return 0; + +err_unlock: + spin_unlock_bh(&ar->beacon_lock); + +err_free: + rcu_read_unlock(); + dev_kfree_skb_any(skb); + return err; +} diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index a61ef3d6..17b0efd 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -105,11 +105,8 @@ static bool ath_hw_keysetmac(struct ath_common *common, if (mac[0] & 0x01) unicast_flag = 0; - macHi = (mac[5] << 8) | mac[4]; - macLo = (mac[3] << 24) | - (mac[2] << 16) | - (mac[1] << 8) | - mac[0]; + macLo = get_unaligned_le32(mac); + macHi = get_unaligned_le16(mac + 4); macLo >>= 1; macLo |= (macHi & 1) << 31; macHi >>= 1; diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 08a2827..c818b0b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -433,6 +433,12 @@ enum { #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */ #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */ +/* BCMA 802.11 core specific IO status (BCMA_IOST) flags */ +#define B43_BCMA_IOST_2G_PHY 0x00000001 /* 2.4G capable phy */ +#define B43_BCMA_IOST_5G_PHY 0x00000002 /* 5G capable phy */ +#define B43_BCMA_IOST_FASTCLKA 0x00000004 /* Fast Clock Available */ +#define B43_BCMA_IOST_DUALB_PHY 0x00000008 /* Dualband phy */ + /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */ #define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ #define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */ @@ -588,6 +594,7 @@ struct b43_dma { struct b43_dmaring *rx_ring; u32 translation; /* Routing bits */ + bool parity; /* Check for parity */ }; struct b43_pio_txqueue; diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c index a5e61a9..64c3f65 100644 --- a/drivers/net/wireless/b43/bus.c +++ b/drivers/net/wireless/b43/bus.c @@ -126,55 +126,52 @@ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core) /* SSB */ #ifdef CONFIG_B43_SSB -static inline int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev) +static int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev) { return ssb_bus_may_powerdown(dev->sdev->bus); } -static inline int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev, +static int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev, bool dynamic_pctl) { return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl); } -static inline int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev) +static int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev) { return ssb_device_is_enabled(dev->sdev); } -static inline void b43_bus_ssb_device_enable(struct b43_bus_dev *dev, +static void b43_bus_ssb_device_enable(struct b43_bus_dev *dev, u32 core_specific_flags) { ssb_device_enable(dev->sdev, core_specific_flags); } -static inline void b43_bus_ssb_device_disable(struct b43_bus_dev *dev, +static void b43_bus_ssb_device_disable(struct b43_bus_dev *dev, u32 core_specific_flags) { ssb_device_disable(dev->sdev, core_specific_flags); } -static inline u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset) +static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset) { return ssb_read16(dev->sdev, offset); } -static inline u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset) +static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset) { return ssb_read32(dev->sdev, offset); } -static inline -void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value) +static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value) { ssb_write16(dev->sdev, offset, value); } -static inline -void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value) +static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value) { ssb_write32(dev->sdev, offset, value); } -static inline -void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer, - size_t count, u16 offset, u8 reg_width) +static void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer, + size_t count, u16 offset, u8 reg_width) { ssb_block_read(dev->sdev, buffer, count, offset, reg_width); } -static inline +static void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer, size_t count, u16 offset, u8 reg_width) { diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index ce572ae..0953ce1 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= (ring->dev->dma.translation << 1); + addrhi |= ring->dev->dma.translation; if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -659,6 +659,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) u32 value; u32 addrext; u32 trans = ring->dev->dma.translation; + bool parity = ring->dev->dma.parity; if (ring->tx) { if (ring->type == B43_DMA_64BIT) { @@ -669,13 +670,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring) value = B43_DMA64_TXENABLE; value |= (addrext << B43_DMA64_TXADDREXT_SHIFT) & B43_DMA64_TXADDREXT_MASK; + if (!parity) + value |= B43_DMA64_TXPARITYDISABLE; b43_dma_write(ring, B43_DMA64_TXCTL, value); b43_dma_write(ring, B43_DMA64_TXRINGLO, (ringbase & 0xFFFFFFFF)); b43_dma_write(ring, B43_DMA64_TXRINGHI, ((ringbase >> 32) & ~SSB_DMA_TRANSLATION_MASK) - | (trans << 1)); + | trans); } else { u32 ringbase = (u32) (ring->dmabase); @@ -684,6 +687,8 @@ static int dmacontroller_setup(struct b43_dmaring *ring) value = B43_DMA32_TXENABLE; value |= (addrext << B43_DMA32_TXADDREXT_SHIFT) & B43_DMA32_TXADDREXT_MASK; + if (!parity) + value |= B43_DMA32_TXPARITYDISABLE; b43_dma_write(ring, B43_DMA32_TXCTL, value); b43_dma_write(ring, B43_DMA32_TXRING, (ringbase & ~SSB_DMA_TRANSLATION_MASK) @@ -702,13 +707,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring) value |= B43_DMA64_RXENABLE; value |= (addrext << B43_DMA64_RXADDREXT_SHIFT) & B43_DMA64_RXADDREXT_MASK; + if (!parity) + value |= B43_DMA64_RXPARITYDISABLE; b43_dma_write(ring, B43_DMA64_RXCTL, value); b43_dma_write(ring, B43_DMA64_RXRINGLO, (ringbase & 0xFFFFFFFF)); b43_dma_write(ring, B43_DMA64_RXRINGHI, ((ringbase >> 32) & ~SSB_DMA_TRANSLATION_MASK) - | (trans << 1)); + | trans); b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots * sizeof(struct b43_dmadesc64)); } else { @@ -720,6 +727,8 @@ static int dmacontroller_setup(struct b43_dmaring *ring) value |= B43_DMA32_RXENABLE; value |= (addrext << B43_DMA32_RXADDREXT_SHIFT) & B43_DMA32_RXADDREXT_MASK; + if (!parity) + value |= B43_DMA32_RXPARITYDISABLE; b43_dma_write(ring, B43_DMA32_RXCTL, value); b43_dma_write(ring, B43_DMA32_RXRING, (ringbase & ~SSB_DMA_TRANSLATION_MASK) @@ -1057,6 +1066,11 @@ int b43_dma_init(struct b43_wldev *dev) return err; switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + dma->translation = bcma_core_dma_translation(dev->dev->bdev); + break; +#endif #ifdef CONFIG_B43_SSB case B43_BUS_SSB: dma->translation = ssb_dma_translation(dev->dev->sdev); @@ -1064,6 +1078,13 @@ int b43_dma_init(struct b43_wldev *dev) #endif } + dma->parity = true; +#ifdef CONFIG_B43_BCMA + /* TODO: find out which SSB devices need disabling parity */ + if (dev->dev->bus_type == B43_BUS_BCMA) + dma->parity = false; +#endif + err = -ENOMEM; /* setup TX DMA channels. */ dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type); diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index e8a80a1..cdf8709 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -20,6 +20,7 @@ #define B43_DMA32_TXSUSPEND 0x00000002 #define B43_DMA32_TXLOOPBACK 0x00000004 #define B43_DMA32_TXFLUSH 0x00000010 +#define B43_DMA32_TXPARITYDISABLE 0x00000800 #define B43_DMA32_TXADDREXT_MASK 0x00030000 #define B43_DMA32_TXADDREXT_SHIFT 16 #define B43_DMA32_TXRING 0x04 @@ -44,6 +45,7 @@ #define B43_DMA32_RXFROFF_MASK 0x000000FE #define B43_DMA32_RXFROFF_SHIFT 1 #define B43_DMA32_RXDIRECTFIFO 0x00000100 +#define B43_DMA32_RXPARITYDISABLE 0x00000800 #define B43_DMA32_RXADDREXT_MASK 0x00030000 #define B43_DMA32_RXADDREXT_SHIFT 16 #define B43_DMA32_RXRING 0x14 @@ -84,6 +86,7 @@ struct b43_dmadesc32 { #define B43_DMA64_TXSUSPEND 0x00000002 #define B43_DMA64_TXLOOPBACK 0x00000004 #define B43_DMA64_TXFLUSH 0x00000010 +#define B43_DMA64_TXPARITYDISABLE 0x00000800 #define B43_DMA64_TXADDREXT_MASK 0x00030000 #define B43_DMA64_TXADDREXT_SHIFT 16 #define B43_DMA64_TXINDEX 0x04 @@ -111,6 +114,7 @@ struct b43_dmadesc32 { #define B43_DMA64_RXFROFF_MASK 0x000000FE #define B43_DMA64_RXFROFF_SHIFT 1 #define B43_DMA64_RXDIRECTFIFO 0x00000100 +#define B43_DMA64_RXPARITYDISABLE 0x00000800 #define B43_DMA64_RXADDREXT_MASK 0x00030000 #define B43_DMA64_RXADDREXT_SHIFT 16 #define B43_DMA64_RXINDEX 0x24 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 092dd93..73fbf03 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1156,17 +1156,37 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) } #ifdef CONFIG_B43_BCMA -static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) +static void b43_bcma_phy_reset(struct b43_wldev *dev) { - u32 flags = 0; + u32 flags; - if (gmode) - flags = B43_BCMA_IOCTL_GMODE; - flags |= B43_BCMA_IOCTL_PHY_CLKEN; + /* Put PHY into reset */ + flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + flags |= B43_BCMA_IOCTL_PHY_RESET; flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */ - b43_device_enable(dev, flags); + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); + udelay(2); + + /* Take PHY out of reset */ + flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + flags &= ~B43_BCMA_IOCTL_PHY_RESET; + flags |= BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); + udelay(1); - /* TODO: reset PHY */ + /* Do not force clock anymore */ + flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + flags &= ~BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); + udelay(1); +} + +static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) +{ + b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); + bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); + b43_bcma_phy_reset(dev); + bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true); } #endif @@ -2814,12 +2834,12 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: - tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL); + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); if (on) tmp |= B43_BCMA_IOCTL_MACPHYCLKEN; else tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN; - bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp); + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); break; #endif #ifdef CONFIG_B43_SSB @@ -4948,6 +4968,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) struct b43_wl *wl = dev->wl; struct pci_dev *pdev = NULL; int err; + u32 tmp; bool have_2ghz_phy = 0, have_5ghz_phy = 0; /* Do NOT do any device initialization here. @@ -4973,17 +4994,17 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: - /* FIXME */ - have_2ghz_phy = 1; - have_5ghz_phy = 0; + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST); + have_2ghz_phy = !!(tmp & B43_BCMA_IOST_2G_PHY); + have_5ghz_phy = !!(tmp & B43_BCMA_IOST_5G_PHY); break; #endif #ifdef CONFIG_B43_SSB case B43_BUS_SSB: if (dev->dev->core_rev >= 5) { - u32 tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH); - have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); - have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); + tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH); + have_2ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_2GHZ_PHY); + have_5ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_5GHZ_PHY); } else B43_WARN_ON(1); break; @@ -5164,6 +5185,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) struct ssb_sprom *sprom = dev->bus_sprom; struct ieee80211_hw *hw; struct b43_wl *wl; + char chip_name[6]; hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops); if (!hw) { @@ -5202,8 +5224,10 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) INIT_WORK(&wl->tx_work, b43_tx_work); skb_queue_head_init(&wl->tx_queue); - b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", - dev->chip_id, dev->core_rev); + snprintf(chip_name, ARRAY_SIZE(chip_name), + (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id); + b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name, + dev->core_rev); return wl; } @@ -5211,19 +5235,59 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) static int b43_bcma_probe(struct bcma_device *core) { struct b43_bus_dev *dev; + struct b43_wl *wl; + int err; dev = b43_bus_dev_bcma_init(core); if (!dev) return -ENODEV; - b43err(NULL, "BCMA is not supported yet!"); - kfree(dev); - return -EOPNOTSUPP; + wl = b43_wireless_init(dev); + if (IS_ERR(wl)) { + err = PTR_ERR(wl); + goto bcma_out; + } + + err = b43_one_core_attach(dev, wl); + if (err) + goto bcma_err_wireless_exit; + + err = ieee80211_register_hw(wl->hw); + if (err) + goto bcma_err_one_core_detach; + b43_leds_register(wl->current_dev); + +bcma_out: + return err; + +bcma_err_one_core_detach: + b43_one_core_detach(dev); +bcma_err_wireless_exit: + ieee80211_free_hw(wl->hw); + return err; } static void b43_bcma_remove(struct bcma_device *core) { - /* TODO */ + struct b43_wldev *wldev = bcma_get_drvdata(core); + struct b43_wl *wl = wldev->wl; + + /* We must cancel any work here before unregistering from ieee80211, + * as the ieee80211 unreg will destroy the workqueue. */ + cancel_work_sync(&wldev->restart_work); + + /* Restore the queues count before unregistering, because firmware detect + * might have modified it. Restoring is important, so the networking + * stack can properly free resources. */ + wl->hw->queues = wl->mac80211_initially_registered_queues; + b43_leds_stop(wldev); + ieee80211_unregister_hw(wl->hw); + + b43_one_core_detach(wldev->dev); + + b43_leds_unregister(wl); + + ieee80211_free_hw(wl->hw); } static struct bcma_driver b43_bcma_driver = { diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 2982103..7c40919 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -148,7 +148,7 @@ static void b43_radio_2059_init(struct b43_wldev *dev) b43_radio_mask(dev, 0x17F, ~0x1); } - b43_radio_mask(dev, 0x11, 0x0008); + b43_radio_mask(dev, 0x11, ~0x0008); } /************************************************** @@ -276,18 +276,25 @@ static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev, if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) b43err(dev->wl, "MAC not suspended\n"); + /* In the following PHY ops we copy wl's dummy behaviour. + * TODO: Find out if reads (currently hidden in masks/masksets) are + * needed and replace following ops with just writes or w&r. + * Note: B43_PHY_HT_RF_CTL1 register is tricky, wrong operation can + * cause delayed (!) machine lock up. */ if (blocked) { - b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0); + b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0); } else { - b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0); - b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x1); - b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0); - b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x2); + b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0); + b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x1); + b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0); + b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x2); if (dev->phy.radio_ver == 0x2059) b43_radio_2059_init(dev); else B43_WARN_ON(1); + + b43_switch_channel(dev, dev->phy.channel); } } @@ -329,7 +336,7 @@ static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - return 1; + return 11; return 36; } diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 95c28f5..1ae1e84 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -611,12 +611,12 @@ static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) switch (dev->dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: - tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL); + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); if (force) tmp |= BCMA_IOCTL_FGC; else tmp &= ~BCMA_IOCTL_FGC; - bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp); + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); break; #endif #ifdef CONFIG_B43_SSB diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c index 23dea4b..f029f6e 100644 --- a/drivers/net/wireless/b43/radio_2059.c +++ b/drivers/net/wireless/b43/radio_2059.c @@ -161,5 +161,14 @@ static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radi const struct b43_phy_ht_channeltab_e_radio2059 *b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq) { + const struct b43_phy_ht_channeltab_e_radio2059 *e; + unsigned int i; + + e = b43_phy_ht_channeltab_radio2059; + for (i = 0; i < ARRAY_SIZE(b43_phy_ht_channeltab_radio2059); i++, e++) { + if (e->freq == freq) + return e; + } + return NULL; } diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 23583be..17a130d 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -532,6 +532,8 @@ struct b43legacy_dma { struct b43legacy_dmaring *rx_ring0; struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */ + + u32 translation; /* Routing bits */ }; /* Data structures for PIO transmission, per 80211 core. */ diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index c33934a..704ee62 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -73,7 +73,7 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring, addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK); addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ssb_dma_translation(ring->dev->dev); + addr |= ring->dev->dma.translation; ctl = (bufsize - ring->frameoffset) & B43legacy_DMA32_DCTL_BYTECNT; if (slot == ring->nr_slots - 1) @@ -175,7 +175,7 @@ static void op64_fill_descriptor(struct b43legacy_dmaring *ring, addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= ssb_dma_translation(ring->dev->dev); + addrhi |= ring->dev->dma.translation; if (slot == ring->nr_slots - 1) ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND; if (start) @@ -709,7 +709,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring) int err = 0; u32 value; u32 addrext; - u32 trans = ssb_dma_translation(ring->dev->dev); + u32 trans = ring->dev->dma.translation; if (ring->tx) { if (ring->type == B43legacy_DMA_64BIT) { @@ -1093,6 +1093,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) return -EOPNOTSUPP; #endif } + dma->translation = ssb_dma_translation(dev->dev); err = -ENOMEM; /* setup TX DMA channels. */ diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 1915039..48ab914 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -5,16 +5,16 @@ iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o -iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o -iwlagn-objs += iwl-rx.o iwl-tx.o iwl-sta.o +iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o +iwlagn-objs += iwl-rx.o iwl-sta.o iwlagn-objs += iwl-scan.o iwl-led.o -iwlagn-objs += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o +iwlagn-objs += iwl-agn-rxon.o iwlagn-objs += iwl-5000.o iwlagn-objs += iwl-6000.o iwlagn-objs += iwl-1000.o iwlagn-objs += iwl-2000.o iwlagn-objs += iwl-pci.o -iwlagn-objs += iwl-trans.o +iwlagn-objs += iwl-trans.o iwl-trans-rx-pcie.o iwl-trans-tx-pcie.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 2f56b34..01b49eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -168,9 +168,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) static struct iwl_lib_ops iwl1000_lib = { .set_hw_params = iwl1000_hw_set_hw_params, - .rx_handler_setup = iwlagn_rx_handler_setup, - .setup_deferred_work = iwlagn_setup_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .nic_config = iwl1000_nic_config, .eeprom_ops = { .regulatory_bands = { @@ -186,10 +183,6 @@ static struct iwl_lib_ops iwl1000_lib = { .temperature = iwlagn_temperature, }; -static const struct iwl_ops iwl1000_ops = { - .lib = &iwl1000_lib, -}; - static struct iwl_base_params iwl1000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -217,7 +210,7 @@ static struct iwl_ht_params iwl1000_ht_params = { .ucode_api_min = IWL1000_UCODE_API_MIN, \ .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ - .ops = &iwl1000_ops, \ + .lib = &iwl1000_lib, \ .base_params = &iwl1000_base_params, \ .led_mode = IWL_LED_BLINK @@ -238,7 +231,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .ucode_api_min = IWL100_UCODE_API_MIN, \ .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ - .ops = &iwl1000_ops, \ + .lib = &iwl1000_lib, \ .base_params = &iwl1000_base_params, \ .led_mode = IWL_LED_RF_STATE, \ .rx_with_siso_diversity = true diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 32ac865..0e13f0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -85,9 +85,6 @@ static void iwl2000_nic_config(struct iwl_priv *priv) if (priv->cfg->iq_invert) iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); - - if (priv->cfg->disable_otp_refresh) - iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010); } static struct iwl_sensitivity_ranges iwl2000_sensitivity = { @@ -156,7 +153,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX); + priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); @@ -167,9 +164,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) static struct iwl_lib_ops iwl2000_lib = { .set_hw_params = iwl2000_hw_set_hw_params, - .rx_handler_setup = iwlagn_rx_handler_setup, - .setup_deferred_work = iwlagn_setup_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .nic_config = iwl2000_nic_config, .eeprom_ops = { .regulatory_bands = { @@ -188,10 +182,9 @@ static struct iwl_lib_ops iwl2000_lib = { static struct iwl_lib_ops iwl2030_lib = { .set_hw_params = iwl2000_hw_set_hw_params, - .rx_handler_setup = iwlagn_bt_rx_handler_setup, - .setup_deferred_work = iwlagn_bt_setup_deferred_work, + .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup, + .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .nic_config = iwl2000_nic_config, .eeprom_ops = { .regulatory_bands = { @@ -208,22 +201,6 @@ static struct iwl_lib_ops iwl2030_lib = { .temperature = iwlagn_temperature, }; -static const struct iwl_ops iwl2000_ops = { - .lib = &iwl2000_lib, -}; - -static const struct iwl_ops iwl2030_ops = { - .lib = &iwl2030_lib, -}; - -static const struct iwl_ops iwl105_ops = { - .lib = &iwl2000_lib, -}; - -static const struct iwl_ops iwl135_ops = { - .lib = &iwl2030_lib, -}; - static struct iwl_base_params iwl2000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, @@ -282,13 +259,12 @@ static struct iwl_bt_params iwl2030_bt_params = { .ucode_api_min = IWL2000_UCODE_API_MIN, \ .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl2000_ops, \ + .lib = &iwl2000_lib, \ .base_params = &iwl2000_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ - .iq_invert = true, \ - .disable_otp_refresh = true \ + .iq_invert = true \ struct iwl_cfg iwl2000_2bgn_cfg = { .name = "2000 Series 2x2 BGN", @@ -307,7 +283,7 @@ struct iwl_cfg iwl2000_2bg_cfg = { .ucode_api_min = IWL2030_UCODE_API_MIN, \ .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl2030_ops, \ + .lib = &iwl2030_lib, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ .need_dc_calib = true, \ @@ -333,13 +309,14 @@ struct iwl_cfg iwl2030_2bg_cfg = { .ucode_api_min = IWL105_UCODE_API_MIN, \ .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl105_ops, \ + .lib = &iwl2000_lib, \ .base_params = &iwl2000_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ .adv_pm = true, \ - .rx_with_siso_diversity = true \ + .rx_with_siso_diversity = true, \ + .iq_invert = true \ struct iwl_cfg iwl105_bg_cfg = { .name = "105 Series 1x1 BG", @@ -358,14 +335,15 @@ struct iwl_cfg iwl105_bgn_cfg = { .ucode_api_min = IWL135_UCODE_API_MIN, \ .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl135_ops, \ + .lib = &iwl2030_lib, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ .adv_pm = true, \ - .rx_with_siso_diversity = true \ + .rx_with_siso_diversity = true, \ + .iq_invert = true \ struct iwl_cfg iwl135_bg_cfg = { .name = "135 Series 1x1 BG/BT", diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5564893..3eeb12e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -315,14 +315,11 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return trans_send_cmd(priv, &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, - .rx_handler_setup = iwlagn_rx_handler_setup, - .setup_deferred_work = iwlagn_setup_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .set_channel_switch = iwl5000_hw_channel_switch, .nic_config = iwl5000_nic_config, .eeprom_ops = { @@ -341,9 +338,6 @@ static struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5150_lib = { .set_hw_params = iwl5150_hw_set_hw_params, - .rx_handler_setup = iwlagn_rx_handler_setup, - .setup_deferred_work = iwlagn_setup_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .set_channel_switch = iwl5000_hw_channel_switch, .nic_config = iwl5000_nic_config, .eeprom_ops = { @@ -360,14 +354,6 @@ static struct iwl_lib_ops iwl5150_lib = { .temperature = iwl5150_temperature, }; -static const struct iwl_ops iwl5000_ops = { - .lib = &iwl5000_lib, -}; - -static const struct iwl_ops iwl5150_ops = { - .lib = &iwl5150_lib, -}; - static struct iwl_base_params iwl5000_base_params = { .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, @@ -390,7 +376,7 @@ static struct iwl_ht_params iwl5000_ht_params = { .ucode_api_min = IWL5000_UCODE_API_MIN, \ .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ - .ops = &iwl5000_ops, \ + .lib = &iwl5000_lib, \ .base_params = &iwl5000_base_params, \ .led_mode = IWL_LED_BLINK @@ -433,7 +419,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .ucode_api_min = IWL5000_UCODE_API_MIN, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .ops = &iwl5000_ops, + .lib = &iwl5000_lib, .base_params = &iwl5000_base_params, .ht_params = &iwl5000_ht_params, .led_mode = IWL_LED_BLINK, @@ -446,7 +432,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .ucode_api_min = IWL5150_UCODE_API_MIN, \ .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ - .ops = &iwl5150_ops, \ + .lib = &iwl5150_lib, \ .base_params = &iwl5000_base_params, \ .need_dc_calib = true, \ .led_mode = IWL_LED_BLINK, \ diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 80f1ef6..973d197 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -106,10 +106,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv) CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); } /* do additional nic configuration if needed */ - if (priv->cfg->ops->nic && - priv->cfg->ops->nic->additional_nic_config) { - priv->cfg->ops->nic->additional_nic_config(priv); - } + if (priv->cfg->additional_nic_config) + priv->cfg->additional_nic_config(priv); } static struct iwl_sensitivity_ranges iwl6000_sensitivity = { @@ -178,7 +176,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX); + priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); @@ -255,14 +253,11 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return trans_send_cmd(priv, &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .rx_handler_setup = iwlagn_rx_handler_setup, - .setup_deferred_work = iwlagn_setup_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, .eeprom_ops = { @@ -282,10 +277,9 @@ static struct iwl_lib_ops iwl6000_lib = { static struct iwl_lib_ops iwl6030_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .rx_handler_setup = iwlagn_bt_rx_handler_setup, - .setup_deferred_work = iwlagn_bt_setup_deferred_work, + .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup, + .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, - .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, .eeprom_ops = { @@ -303,32 +297,6 @@ static struct iwl_lib_ops iwl6030_lib = { .temperature = iwlagn_temperature, }; -static struct iwl_nic_ops iwl6050_nic_ops = { - .additional_nic_config = &iwl6050_additional_nic_config, -}; - -static struct iwl_nic_ops iwl6150_nic_ops = { - .additional_nic_config = &iwl6150_additional_nic_config, -}; - -static const struct iwl_ops iwl6000_ops = { - .lib = &iwl6000_lib, -}; - -static const struct iwl_ops iwl6050_ops = { - .lib = &iwl6000_lib, - .nic = &iwl6050_nic_ops, -}; - -static const struct iwl_ops iwl6150_ops = { - .lib = &iwl6000_lib, - .nic = &iwl6150_nic_ops, -}; - -static const struct iwl_ops iwl6030_ops = { - .lib = &iwl6030_lib, -}; - static struct iwl_base_params iwl6000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, @@ -402,7 +370,7 @@ static struct iwl_bt_params iwl6000_bt_params = { .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ - .ops = &iwl6000_ops, \ + .lib = &iwl6000_lib, \ .base_params = &iwl6000_g2_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ @@ -430,7 +398,7 @@ struct iwl_cfg iwl6005_2bg_cfg = { .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ - .ops = &iwl6030_ops, \ + .lib = &iwl6030_lib, \ .base_params = &iwl6000_g2_base_params, \ .bt_params = &iwl6000_bt_params, \ .need_dc_calib = true, \ @@ -511,7 +479,7 @@ struct iwl_cfg iwl130_bg_cfg = { .valid_rx_ant = ANT_BC, /* .cfg overwrite */ \ .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ - .ops = &iwl6000_ops, \ + .lib = &iwl6000_lib, \ .base_params = &iwl6000_base_params, \ .pa_type = IWL_PA_INTERNAL, \ .led_mode = IWL_LED_BLINK @@ -538,7 +506,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .ucode_api_min = IWL6050_UCODE_API_MIN, \ .valid_tx_ant = ANT_AB, /* .cfg overwrite */ \ .valid_rx_ant = ANT_AB, /* .cfg overwrite */ \ - .ops = &iwl6050_ops, \ + .lib = &iwl6000_lib, \ + .additional_nic_config = iwl6050_additional_nic_config, \ .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ .base_params = &iwl6050_base_params, \ @@ -561,7 +530,8 @@ struct iwl_cfg iwl6050_2abg_cfg = { .fw_name_pre = IWL6050_FW_PRE, \ .ucode_api_max = IWL6050_UCODE_API_MAX, \ .ucode_api_min = IWL6050_UCODE_API_MIN, \ - .ops = &iwl6150_ops, \ + .lib = &iwl6000_lib, \ + .additional_nic_config = iwl6150_additional_nic_config, \ .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ .base_params = &iwl6050_base_params, \ @@ -587,7 +557,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .ucode_api_min = IWL6000_UCODE_API_MIN, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, - .ops = &iwl6000_ops, + .lib = &iwl6000_lib, .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 02c7c65..72d6297 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -98,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = trans_send_cmd(priv, &hcmd); + ret = trans_send_cmd(&priv->trans, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", ret, i); @@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - return trans_send_cmd(priv, &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -548,7 +548,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); - return trans_send_cmd(priv, &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) @@ -840,6 +840,65 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, active_chains); } +static void iwlagn_gain_computation(struct iwl_priv *priv, + u32 average_noise[NUM_RX_CHAINS], + u16 min_average_noise_antenna_i, + u32 min_average_noise, + u8 default_chain) +{ + int i; + s32 delta_g; + struct iwl_chain_noise_data *data = &priv->chain_noise_data; + + /* + * Find Gain Code for the chains based on "default chain" + */ + for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { + if ((data->disconn_array[i])) { + data->delta_gain_code[i] = 0; + continue; + } + + delta_g = (priv->cfg->base_params->chain_noise_scale * + ((s32)average_noise[default_chain] - + (s32)average_noise[i])) / 1500; + + /* bound gain by 2 bits value max, 3rd bit is sign */ + data->delta_gain_code[i] = + min(abs(delta_g), + (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); + + if (delta_g < 0) + /* + * set negative sign ... + * note to Intel developers: This is uCode API format, + * not the format of any internal device registers. + * Do not change this format for e.g. 6050 or similar + * devices. Change format only if more resolution + * (i.e. more than 2 bits magnitude) is needed. + */ + data->delta_gain_code[i] |= (1 << 2); + } + + IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", + data->delta_gain_code[1], data->delta_gain_code[2]); + + if (!data->radio_write) { + struct iwl_calib_chain_noise_gain_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + iwl_set_calib_hdr(&cmd.hdr, + priv->phy_calib_chain_noise_gain_cmd); + cmd.delta_gain_1 = data->delta_gain_code[1]; + cmd.delta_gain_2 = data->delta_gain_code[2]; + trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, + CMD_ASYNC, sizeof(cmd), &cmd); + + data->radio_write = 1; + data->state = IWL_CHAIN_NOISE_CALIBRATED; + } +} /* * Accumulate 16 beacons of signal and noise statistics for each of diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c deleted file mode 100644 index f0f5f5e..0000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ /dev/null @@ -1,210 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless <ilw@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-agn.h" -#include "iwl-trans.h" - -int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) -{ - struct iwl_tx_ant_config_cmd tx_ant_cmd = { - .valid = cpu_to_le32(valid_tx_ant), - }; - - if (IWL_UCODE_API(priv->ucode_ver) > 1) { - IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return trans_send_cmd_pdu(priv, - TX_ANT_CONFIGURATION_CMD, - CMD_SYNC, - sizeof(struct iwl_tx_ant_config_cmd), - &tx_ant_cmd); - } else { - IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); - return -EOPNOTSUPP; - } -} - -void iwlagn_gain_computation(struct iwl_priv *priv, - u32 average_noise[NUM_RX_CHAINS], - u16 min_average_noise_antenna_i, - u32 min_average_noise, - u8 default_chain) -{ - int i; - s32 delta_g; - struct iwl_chain_noise_data *data = &priv->chain_noise_data; - - /* - * Find Gain Code for the chains based on "default chain" - */ - for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { - if ((data->disconn_array[i])) { - data->delta_gain_code[i] = 0; - continue; - } - - delta_g = (priv->cfg->base_params->chain_noise_scale * - ((s32)average_noise[default_chain] - - (s32)average_noise[i])) / 1500; - - /* bound gain by 2 bits value max, 3rd bit is sign */ - data->delta_gain_code[i] = - min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); - - if (delta_g < 0) - /* - * set negative sign ... - * note to Intel developers: This is uCode API format, - * not the format of any internal device registers. - * Do not change this format for e.g. 6050 or similar - * devices. Change format only if more resolution - * (i.e. more than 2 bits magnitude) is needed. - */ - data->delta_gain_code[i] |= (1 << 2); - } - - IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", - data->delta_gain_code[1], data->delta_gain_code[2]); - - if (!data->radio_write) { - struct iwl_calib_chain_noise_gain_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - - iwl_set_calib_hdr(&cmd.hdr, - priv->_agn.phy_calib_chain_noise_gain_cmd); - cmd.delta_gain_1 = data->delta_gain_code[1]; - cmd.delta_gain_2 = data->delta_gain_code[2]; - trans_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, - CMD_ASYNC, sizeof(cmd), &cmd); - - data->radio_write = 1; - data->state = IWL_CHAIN_NOISE_CALIBRATED; - } -} - -int iwlagn_set_pan_params(struct iwl_priv *priv) -{ - struct iwl_wipan_params_cmd cmd; - struct iwl_rxon_context *ctx_bss, *ctx_pan; - int slot0 = 300, slot1 = 0; - int ret; - - if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) - return 0; - - BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); - - lockdep_assert_held(&priv->mutex); - - ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; - ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; - - /* - * If the PAN context is inactive, then we don't need - * to update the PAN parameters, the last thing we'll - * have done before it goes inactive is making the PAN - * parameters be WLAN-only. - */ - if (!ctx_pan->is_active) - return 0; - - memset(&cmd, 0, sizeof(cmd)); - - /* only 2 slots are currently allowed */ - cmd.num_slots = 2; - - cmd.slots[0].type = 0; /* BSS */ - cmd.slots[1].type = 1; /* PAN */ - - if (priv->_agn.hw_roc_channel) { - /* both contexts must be used for this to happen */ - slot1 = priv->_agn.hw_roc_duration; - slot0 = IWL_MIN_SLOT_TIME; - } else if (ctx_bss->vif && ctx_pan->vif) { - int bcnint = ctx_pan->vif->bss_conf.beacon_int; - int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; - - /* should be set, but seems unused?? */ - cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); - - if (ctx_pan->vif->type == NL80211_IFTYPE_AP && - bcnint && - bcnint != ctx_bss->vif->bss_conf.beacon_int) { - IWL_ERR(priv, - "beacon intervals don't match (%d, %d)\n", - ctx_bss->vif->bss_conf.beacon_int, - ctx_pan->vif->bss_conf.beacon_int); - } else - bcnint = max_t(int, bcnint, - ctx_bss->vif->bss_conf.beacon_int); - if (!bcnint) - bcnint = DEFAULT_BEACON_INTERVAL; - slot0 = bcnint / 2; - slot1 = bcnint - slot0; - - if (test_bit(STATUS_SCAN_HW, &priv->status) || - (!ctx_bss->vif->bss_conf.idle && - !ctx_bss->vif->bss_conf.assoc)) { - slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; - slot1 = IWL_MIN_SLOT_TIME; - } else if (!ctx_pan->vif->bss_conf.idle && - !ctx_pan->vif->bss_conf.assoc) { - slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME; - slot0 = IWL_MIN_SLOT_TIME; - } - } else if (ctx_pan->vif) { - slot0 = 0; - slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * - ctx_pan->vif->bss_conf.beacon_int; - slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); - - if (test_bit(STATUS_SCAN_HW, &priv->status)) { - slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; - slot1 = IWL_MIN_SLOT_TIME; - } - } - - cmd.slots[0].width = cpu_to_le16(slot0); - cmd.slots[1].width = cpu_to_le16(slot1); - - ret = trans_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC, - sizeof(cmd), &cmd); - if (ret) - IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); - - return ret; -} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c deleted file mode 100644 index f1b40ec..0000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ /dev/null @@ -1,306 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless <ilw@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/etherdevice.h> -#include <linux/sched.h> -#include <linux/gfp.h> -#include <net/mac80211.h> - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-agn.h" -#include "iwl-helpers.h" - -#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) - -/* Free dram table */ -void iwl_free_isr_ict(struct iwl_priv *priv) -{ - if (priv->_agn.ict_tbl_vir) { - dma_free_coherent(priv->bus.dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - priv->_agn.ict_tbl_vir, - priv->_agn.ict_tbl_dma); - priv->_agn.ict_tbl_vir = NULL; - } -} - - -/* allocate dram shared table it is a PAGE_SIZE aligned - * also reset all data related to ICT table interrupt. - */ -int iwl_alloc_isr_ict(struct iwl_priv *priv) -{ - - /* allocate shrared data table */ - priv->_agn.ict_tbl_vir = - dma_alloc_coherent(priv->bus.dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &priv->_agn.ict_tbl_dma, GFP_KERNEL); - if (!priv->_agn.ict_tbl_vir) - return -ENOMEM; - - /* align table to PAGE_SIZE boundary */ - priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE); - - IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)priv->_agn.ict_tbl_dma, - (unsigned long long)priv->_agn.aligned_ict_tbl_dma, - (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); - - priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir + - (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma); - - IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", - priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir, - (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); - - /* reset table and index to all 0 */ - memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - priv->_agn.ict_index = 0; - - /* add periodic RX interrupt */ - priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; - return 0; -} - -/* Device is going up inform it about using ICT interrupt table, - * also we need to tell the driver to start using ICT interrupt. - */ -int iwl_reset_ict(struct iwl_priv *priv) -{ - u32 val; - unsigned long flags; - - if (!priv->_agn.ict_tbl_vir) - return 0; - - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - - memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - - val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT; - - val |= CSR_DRAM_INT_TBL_ENABLE; - val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - - IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " - "aligned dma address %Lx\n", - val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma); - - iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); - priv->_agn.use_ict = true; - priv->_agn.ict_index = 0; - iwl_write32(priv, CSR_INT, priv->inta_mask); - iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -/* Device is going down disable ict interrupt usage */ -void iwl_disable_ict(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - priv->_agn.use_ict = false; - spin_unlock_irqrestore(&priv->lock, flags); -} - -static irqreturn_t iwl_isr(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - unsigned long flags; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_fh; -#endif - if (!priv) - return IRQ_NONE; - - spin_lock_irqsave(&priv->lock, flags); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!inta) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); - goto none; - } - - if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared. It might have already raised - * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); - goto unplugged; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " - "fh 0x%08x\n", inta, inta_mask, inta_fh); - } -#endif - - priv->_agn.inta |= inta; - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) - iwl_enable_interrupts(priv); - - unplugged: - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) - iwl_enable_interrupts(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_NONE; -} - -/* interrupt handler using ict table, with this interrupt driver will - * stop using INTA register to get device's interrupt, reading this register - * is expensive, device will write interrupts in ICT dram table, increment - * index then will fire interrupt to driver, driver will OR all ICT table - * entries from current index up to table entry with 0 value. the result is - * the interrupt we need to service, driver will set the entries back to 0 and - * set index. - */ -irqreturn_t iwl_isr_ict(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - u32 val = 0; - unsigned long flags; - - if (!priv) - return IRQ_NONE; - - /* dram interrupt table not set yet, - * use legacy interrupt. - */ - if (!priv->_agn.use_ict) - return iwl_isr(irq, data); - - spin_lock_irqsave(&priv->lock, flags); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. - */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); - goto none; - } - - /* read all entries that not 0 start with ict_index */ - while (priv->_agn.ict_tbl[priv->_agn.ict_index]) { - - val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]); - IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", - priv->_agn.ict_index, - le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index])); - priv->_agn.ict_tbl[priv->_agn.ict_index] = 0; - priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index, - ICT_COUNT); - - } - - /* We should not get this value, just ignore it. */ - if (val == 0xffffffff) - val = 0; - - /* - * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit - * (bit 15 before shifting it to 31) to clear when using interrupt - * coalescing. fortunately, bits 18 and 19 stay set when this happens - * so we use them to decide on the real state of the Rx bit. - * In order words, bit 15 is set if bit 18 or bit 19 are set. - */ - if (val & 0xC0000) - val |= 0x8000; - - inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", - inta, inta_mask, val); - - inta &= priv->inta_mask; - priv->_agn.inta |= inta; - - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) { - /* Allow interrupt if was disabled by this handler and - * no tasklet was schedules, We should not enable interrupt, - * tasklet will enable it. - */ - iwl_enable_interrupts(priv); - } - - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. - * only Re-enable if disabled by irq. - */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) - iwl_enable_interrupts(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_NONE; -} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index eb2be0d..3bee0f11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -53,73 +53,73 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) switch (status) { case TX_STATUS_POSTPONE_DELAY: - priv->_agn.reply_tx_stats.pp_delay++; + priv->reply_tx_stats.pp_delay++; break; case TX_STATUS_POSTPONE_FEW_BYTES: - priv->_agn.reply_tx_stats.pp_few_bytes++; + priv->reply_tx_stats.pp_few_bytes++; break; case TX_STATUS_POSTPONE_BT_PRIO: - priv->_agn.reply_tx_stats.pp_bt_prio++; + priv->reply_tx_stats.pp_bt_prio++; break; case TX_STATUS_POSTPONE_QUIET_PERIOD: - priv->_agn.reply_tx_stats.pp_quiet_period++; + priv->reply_tx_stats.pp_quiet_period++; break; case TX_STATUS_POSTPONE_CALC_TTAK: - priv->_agn.reply_tx_stats.pp_calc_ttak++; + priv->reply_tx_stats.pp_calc_ttak++; break; case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: - priv->_agn.reply_tx_stats.int_crossed_retry++; + priv->reply_tx_stats.int_crossed_retry++; break; case TX_STATUS_FAIL_SHORT_LIMIT: - priv->_agn.reply_tx_stats.short_limit++; + priv->reply_tx_stats.short_limit++; break; case TX_STATUS_FAIL_LONG_LIMIT: - priv->_agn.reply_tx_stats.long_limit++; + priv->reply_tx_stats.long_limit++; break; case TX_STATUS_FAIL_FIFO_UNDERRUN: - priv->_agn.reply_tx_stats.fifo_underrun++; + priv->reply_tx_stats.fifo_underrun++; break; case TX_STATUS_FAIL_DRAIN_FLOW: - priv->_agn.reply_tx_stats.drain_flow++; + priv->reply_tx_stats.drain_flow++; break; case TX_STATUS_FAIL_RFKILL_FLUSH: - priv->_agn.reply_tx_stats.rfkill_flush++; + priv->reply_tx_stats.rfkill_flush++; break; case TX_STATUS_FAIL_LIFE_EXPIRE: - priv->_agn.reply_tx_stats.life_expire++; + priv->reply_tx_stats.life_expire++; break; case TX_STATUS_FAIL_DEST_PS: - priv->_agn.reply_tx_stats.dest_ps++; + priv->reply_tx_stats.dest_ps++; break; case TX_STATUS_FAIL_HOST_ABORTED: - priv->_agn.reply_tx_stats.host_abort++; + priv->reply_tx_stats.host_abort++; break; case TX_STATUS_FAIL_BT_RETRY: - priv->_agn.reply_tx_stats.bt_retry++; + priv->reply_tx_stats.bt_retry++; break; case TX_STATUS_FAIL_STA_INVALID: - priv->_agn.reply_tx_stats.sta_invalid++; + priv->reply_tx_stats.sta_invalid++; break; case TX_STATUS_FAIL_FRAG_DROPPED: - priv->_agn.reply_tx_stats.frag_drop++; + priv->reply_tx_stats.frag_drop++; break; case TX_STATUS_FAIL_TID_DISABLE: - priv->_agn.reply_tx_stats.tid_disable++; + priv->reply_tx_stats.tid_disable++; break; case TX_STATUS_FAIL_FIFO_FLUSHED: - priv->_agn.reply_tx_stats.fifo_flush++; + priv->reply_tx_stats.fifo_flush++; break; case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: - priv->_agn.reply_tx_stats.insuff_cf_poll++; + priv->reply_tx_stats.insuff_cf_poll++; break; case TX_STATUS_FAIL_PASSIVE_NO_RX: - priv->_agn.reply_tx_stats.fail_hw_drop++; + priv->reply_tx_stats.fail_hw_drop++; break; case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: - priv->_agn.reply_tx_stats.sta_color_mismatch++; + priv->reply_tx_stats.sta_color_mismatch++; break; default: - priv->_agn.reply_tx_stats.unknown++; + priv->reply_tx_stats.unknown++; break; } } @@ -130,43 +130,43 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) switch (status) { case AGG_TX_STATE_UNDERRUN_MSK: - priv->_agn.reply_agg_tx_stats.underrun++; + priv->reply_agg_tx_stats.underrun++; break; case AGG_TX_STATE_BT_PRIO_MSK: - priv->_agn.reply_agg_tx_stats.bt_prio++; + priv->reply_agg_tx_stats.bt_prio++; break; case AGG_TX_STATE_FEW_BYTES_MSK: - priv->_agn.reply_agg_tx_stats.few_bytes++; + priv->reply_agg_tx_stats.few_bytes++; break; case AGG_TX_STATE_ABORT_MSK: - priv->_agn.reply_agg_tx_stats.abort++; + priv->reply_agg_tx_stats.abort++; break; case AGG_TX_STATE_LAST_SENT_TTL_MSK: - priv->_agn.reply_agg_tx_stats.last_sent_ttl++; + priv->reply_agg_tx_stats.last_sent_ttl++; break; case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: - priv->_agn.reply_agg_tx_stats.last_sent_try++; + priv->reply_agg_tx_stats.last_sent_try++; break; case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: - priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++; + priv->reply_agg_tx_stats.last_sent_bt_kill++; break; case AGG_TX_STATE_SCD_QUERY_MSK: - priv->_agn.reply_agg_tx_stats.scd_query++; + priv->reply_agg_tx_stats.scd_query++; break; case AGG_TX_STATE_TEST_BAD_CRC32_MSK: - priv->_agn.reply_agg_tx_stats.bad_crc32++; + priv->reply_agg_tx_stats.bad_crc32++; break; case AGG_TX_STATE_RESPONSE_MSK: - priv->_agn.reply_agg_tx_stats.response++; + priv->reply_agg_tx_stats.response++; break; case AGG_TX_STATE_DUMP_TX_MSK: - priv->_agn.reply_agg_tx_stats.dump_tx++; + priv->reply_agg_tx_stats.dump_tx++; break; case AGG_TX_STATE_DELAY_TX_MSK: - priv->_agn.reply_agg_tx_stats.delay_tx++; + priv->reply_agg_tx_stats.delay_tx++; break; default: - priv->_agn.reply_agg_tx_stats.unknown++; + priv->reply_agg_tx_stats.unknown++; break; } } @@ -391,8 +391,7 @@ void iwl_check_abort_status(struct iwl_priv *priv, } } -static void iwlagn_rx_reply_tx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -401,6 +400,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct ieee80211_tx_info *info; struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + struct ieee80211_hdr *hdr; struct iwl_tx_info *txb; u32 status = le16_to_cpu(tx_resp->status.status); int tid; @@ -427,6 +427,11 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, IWLAGN_TX_RES_RA_POS; spin_lock_irqsave(&priv->sta_lock, flags); + + hdr = (void *)txb->skb->data; + if (!ieee80211_is_data_qos(hdr->frame_control)) + priv->last_seq_ctl = tx_resp->seq_ctl; + if (txq->sched_retry) { const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); struct iwl_ht_agg *agg; @@ -479,27 +484,6 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); } -void iwlagn_rx_handler_setup(struct iwl_priv *priv) -{ - /* init calibration handlers */ - priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = - iwlagn_rx_calib_result; - priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; - - /* set up notification wait support */ - spin_lock_init(&priv->_agn.notif_wait_lock); - INIT_LIST_HEAD(&priv->_agn.notif_waits); - init_waitqueue_head(&priv->_agn.notif_waitq); -} - -void iwlagn_setup_deferred_work(struct iwl_priv *priv) -{ - /* - * nothing need to be done here anymore - * still keep for future use if needed - */ -} - int iwlagn_hw_valid_rtc_data_addr(u32 addr) { return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && @@ -541,7 +525,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return trans_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -628,283 +612,6 @@ struct iwl_mod_params iwlagn_mod_params = { /* the rest are 0 by default */ }; -int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - u32 rb_size; - const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ - u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - - rb_timeout = RX_RB_TIMEOUT; - - if (iwlagn_mod_params.amsdu_size_8K) - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; - else - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; - - /* Stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - - /* Reset driver's Rx queue write index */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); - - /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - (u32)(rxq->bd_dma >> 8)); - - /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - rxq->rb_stts_dma >> 4); - - /* Enable Rx DMA - * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in - * the credit mechanism in 5000 HW RX FIFO - * Direct rx interrupts to hosts - * Rx buffer size 4 or 8k - * RB timeout 0x10 - * 256 RBDs - */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | - rb_size| - (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| - (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - - /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); - - return 0; -} - -static void iwlagn_set_pwr_vmain(struct iwl_priv *priv) -{ -/* - * (for documentation purposes) - * to set power to V_AUX, do: - - if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - */ - - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); -} - -int iwlagn_hw_nic_init(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl_rx_queue *rxq = &priv->rxq; - - /* nic_init */ - spin_lock_irqsave(&priv->lock, flags); - iwl_apm_init(priv); - - /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - - spin_unlock_irqrestore(&priv->lock, flags); - - iwlagn_set_pwr_vmain(priv); - - priv->cfg->ops->lib->nic_config(priv); - - /* Allocate the RX queue, or reset if it is already allocated */ - trans_rx_init(priv); - - iwlagn_rx_replenish(priv); - - iwlagn_rx_init(priv, rxq); - - spin_lock_irqsave(&priv->lock, flags); - - rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(priv, rxq); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Allocate or reset and init all Tx and Command queues */ - if (trans_tx_init(priv)) - return -ENOMEM; - - if (priv->cfg->base_params->shadow_reg_enable) { - /* enable shadow regs in HW */ - iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, - 0x800FFFFF); - } - - set_bit(STATUS_INIT, &priv->status); - - return 0; -} - -/** - * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr - */ -static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, - dma_addr_t dma_addr) -{ - return cpu_to_le32((u32)(dma_addr >> 8)); -} - -/** - * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool - * - * If there are slots in the RX queue that need to be restocked, - * and we have free pre-allocated buffers, fill the ranks as much - * as we can, pulling from rx_free. - * - * This moves the 'write' index forward to catch up with 'processed', and - * also updates the memory address in the firmware to reference the new - * target buffer. - */ -void iwlagn_rx_queue_restock(struct iwl_priv *priv) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - unsigned long flags; - - spin_lock_irqsave(&rxq->lock, flags); - while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { - /* The overwritten rxb must be a used one */ - rxb = rxq->queue[rxq->write]; - BUG_ON(rxb && rxb->page); - - /* Get next free Rx buffer, remove from free list */ - element = rxq->rx_free.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, - rxb->page_dma); - rxq->queue[rxq->write] = rxb; - rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; - rxq->free_count--; - } - spin_unlock_irqrestore(&rxq->lock, flags); - /* If the pre-allocated buffer pool is dropping low, schedule to - * refill it */ - if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->workqueue, &priv->rx_replenish); - - - /* If we've added more space for the firmware to place data, tell it. - * Increment device's write pointer in multiples of 8. */ - if (rxq->write_actual != (rxq->write & ~0x7)) { - spin_lock_irqsave(&rxq->lock, flags); - rxq->need_update = 1; - spin_unlock_irqrestore(&rxq->lock, flags); - iwl_rx_queue_update_write_ptr(priv, rxq); - } -} - -/** - * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free - * - * When moving to rx_free an SKB is allocated for the slot. - * - * Also restock the Rx queue via iwl_rx_queue_restock. - * This is called as a scheduled work item (except for during initialization) - */ -void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - struct page *page; - unsigned long flags; - gfp_t gfp_mask = priority; - - while (1) { - spin_lock_irqsave(&rxq->lock, flags); - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - return; - } - spin_unlock_irqrestore(&rxq->lock, flags); - - if (rxq->free_count > RX_LOW_WATERMARK) - gfp_mask |= __GFP_NOWARN; - - if (priv->hw_params.rx_page_order > 0) - gfp_mask |= __GFP_COMP; - - /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); - if (!page) { - if (net_ratelimit()) - IWL_DEBUG_INFO(priv, "alloc_pages failed, " - "order: %d\n", - priv->hw_params.rx_page_order); - - if ((rxq->free_count <= RX_LOW_WATERMARK) && - net_ratelimit()) - IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", - priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", - rxq->free_count); - /* We don't reschedule replenish work here -- we will - * call the restock method and if it still needs - * more buffers it will schedule replenish */ - return; - } - - spin_lock_irqsave(&rxq->lock, flags); - - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, priv->hw_params.rx_page_order); - return; - } - element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - spin_unlock_irqrestore(&rxq->lock, flags); - - BUG_ON(rxb->page); - rxb->page = page; - /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(priv->bus.dev, page, 0, - PAGE_SIZE << priv->hw_params.rx_page_order, - DMA_FROM_DEVICE); - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); - - spin_lock_irqsave(&rxq->lock, flags); - - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - - spin_unlock_irqrestore(&rxq->lock, flags); - } -} - -void iwlagn_rx_replenish(struct iwl_priv *priv) -{ - unsigned long flags; - - iwlagn_rx_allocate(priv, GFP_KERNEL); - - spin_lock_irqsave(&priv->lock, flags); - iwlagn_rx_queue_restock(priv); - spin_unlock_irqrestore(&priv->lock, flags); -} - -void iwlagn_rx_replenish_now(struct iwl_priv *priv) -{ - iwlagn_rx_allocate(priv, GFP_ATOMIC); - - iwlagn_rx_queue_restock(priv); -} - int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) { int idx = 0; @@ -1048,7 +755,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen) { - struct sk_buff *skb = priv->_agn.offchan_tx_skb; + struct sk_buff *skb = priv->offchan_tx_skb; if (skb->len < maxlen) maxlen = skb->len; @@ -1134,7 +841,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) } else if (priv->scan_type == IWL_SCAN_OFFCH_TX) { scan->suspend_time = 0; scan->max_out_time = - cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout); + cpu_to_le32(1024 * priv->offchan_tx_timeout); } switch (priv->scan_type) { @@ -1322,9 +1029,9 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan_ch = (void *)&scan->data[cmd_len]; scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; scan_ch->channel = - cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value); + cpu_to_le16(priv->offchan_tx_chan->hw_value); scan_ch->active_dwell = - cpu_to_le16(priv->_agn.offchan_tx_timeout); + cpu_to_le16(priv->offchan_tx_timeout); scan_ch->passive_dwell = 0; /* Set txpower levels to defaults */ @@ -1334,7 +1041,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) * power level: * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; */ - if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ) + if (priv->offchan_tx_chan->band == IEEE80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); @@ -1360,7 +1067,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (ret) return ret; - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) { clear_bit(STATUS_SCAN_HW, &priv->status); iwlagn_set_pan_params(priv); @@ -1466,7 +1173,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) flush_cmd.fifo_control); flush_cmd.flush_control = cpu_to_le16(flush_control); - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) @@ -1660,12 +1367,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (priv->cfg->bt_params->bt_session_2) { memcpy(&bt_cmd_2000.basic, &basic, sizeof(basic)); - ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); } else { memcpy(&bt_cmd_6000.basic, &basic, sizeof(basic)); - ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); } if (ret) @@ -1986,15 +1693,12 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) { - iwlagn_rx_handler_setup(priv); priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] = iwlagn_bt_coex_profile_notif; } void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv) { - iwlagn_setup_deferred_work(priv); - INIT_WORK(&priv->bt_traffic_change_work, iwlagn_bt_traffic_change_work); } @@ -2306,9 +2010,9 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv, wait_entry->triggered = false; wait_entry->aborted = false; - spin_lock_bh(&priv->_agn.notif_wait_lock); - list_add(&wait_entry->list, &priv->_agn.notif_waits); - spin_unlock_bh(&priv->_agn.notif_wait_lock); + spin_lock_bh(&priv->notif_wait_lock); + list_add(&wait_entry->list, &priv->notif_waits); + spin_unlock_bh(&priv->notif_wait_lock); } int iwlagn_wait_notification(struct iwl_priv *priv, @@ -2317,13 +2021,13 @@ int iwlagn_wait_notification(struct iwl_priv *priv, { int ret; - ret = wait_event_timeout(priv->_agn.notif_waitq, + ret = wait_event_timeout(priv->notif_waitq, wait_entry->triggered || wait_entry->aborted, timeout); - spin_lock_bh(&priv->_agn.notif_wait_lock); + spin_lock_bh(&priv->notif_wait_lock); list_del(&wait_entry->list); - spin_unlock_bh(&priv->_agn.notif_wait_lock); + spin_unlock_bh(&priv->notif_wait_lock); if (wait_entry->aborted) return -EIO; @@ -2337,93 +2041,7 @@ int iwlagn_wait_notification(struct iwl_priv *priv, void iwlagn_remove_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry) { - spin_lock_bh(&priv->_agn.notif_wait_lock); + spin_lock_bh(&priv->notif_wait_lock); list_del(&wait_entry->list); - spin_unlock_bh(&priv->_agn.notif_wait_lock); -} - -int iwlagn_start_device(struct iwl_priv *priv) -{ - int ret; - - if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_prepare_card_hw(priv)) { - IWL_WARN(priv, "Exit HW not ready\n"); - return -EIO; - } - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - if (iwl_is_rfkill(priv)) { - wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - iwl_enable_interrupts(priv); - return -ERFKILL; - } - - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - - ret = iwlagn_hw_nic_init(priv); - if (ret) { - IWL_ERR(priv, "Unable to init nic\n"); - return ret; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - return 0; -} - -void iwlagn_stop_device(struct iwl_priv *priv) -{ - unsigned long flags; - - /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - - /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); - - /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); - - /* - * If a HW restart happens during firmware loading, - * then the firmware loading might call this function - * and later it might be called again due to the - * restart. So don't process again if the device is - * already dead. - */ - if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { - trans_tx_stop(priv); - trans_rx_stop(priv); - - /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); - udelay(5); - } - - /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv); + spin_unlock_bh(&priv->notif_wait_lock); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ebcd13b..3789ff4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -354,9 +354,11 @@ static void rs_program_fix_rate(struct iwl_priv *priv, lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL /* testmode has higher priority to overwirte the fixed rate */ if (priv->tm_fixed_rate) lq_sta->dbg_fixed_rate = priv->tm_fixed_rate; +#endif IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); @@ -1080,7 +1082,8 @@ done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); -#ifdef CONFIG_MAC80211_DEBUGFS + +#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL) if ((priv->tm_fixed_rate) && (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) rs_program_fix_rate(priv, lq_sta); @@ -2904,8 +2907,9 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i if (sband->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; - +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL priv->tm_fixed_rate = 0; +#endif #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->dbg_fixed_rate = 0; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index dc64f25..d42ef17 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -40,7 +40,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -66,7 +66,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -92,7 +92,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -121,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - ret = trans_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) @@ -180,7 +180,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = trans_send_cmd_pdu(priv, ctx->rxon_assoc_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; } @@ -266,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ - ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -303,6 +303,98 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, return 0; } +int iwlagn_set_pan_params(struct iwl_priv *priv) +{ + struct iwl_wipan_params_cmd cmd; + struct iwl_rxon_context *ctx_bss, *ctx_pan; + int slot0 = 300, slot1 = 0; + int ret; + + if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) + return 0; + + BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); + + lockdep_assert_held(&priv->mutex); + + ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; + ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; + + /* + * If the PAN context is inactive, then we don't need + * to update the PAN parameters, the last thing we'll + * have done before it goes inactive is making the PAN + * parameters be WLAN-only. + */ + if (!ctx_pan->is_active) + return 0; + + memset(&cmd, 0, sizeof(cmd)); + + /* only 2 slots are currently allowed */ + cmd.num_slots = 2; + + cmd.slots[0].type = 0; /* BSS */ + cmd.slots[1].type = 1; /* PAN */ + + if (priv->hw_roc_channel) { + /* both contexts must be used for this to happen */ + slot1 = priv->hw_roc_duration; + slot0 = IWL_MIN_SLOT_TIME; + } else if (ctx_bss->vif && ctx_pan->vif) { + int bcnint = ctx_pan->beacon_int; + int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; + + /* should be set, but seems unused?? */ + cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE); + + if (ctx_pan->vif->type == NL80211_IFTYPE_AP && + bcnint && + bcnint != ctx_bss->beacon_int) { + IWL_ERR(priv, + "beacon intervals don't match (%d, %d)\n", + ctx_bss->beacon_int, ctx_pan->beacon_int); + } else + bcnint = max_t(int, bcnint, + ctx_bss->beacon_int); + if (!bcnint) + bcnint = DEFAULT_BEACON_INTERVAL; + slot0 = bcnint / 2; + slot1 = bcnint - slot0; + + if (test_bit(STATUS_SCAN_HW, &priv->status) || + (!ctx_bss->vif->bss_conf.idle && + !ctx_bss->vif->bss_conf.assoc)) { + slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; + slot1 = IWL_MIN_SLOT_TIME; + } else if (!ctx_pan->vif->bss_conf.idle && + !ctx_pan->vif->bss_conf.assoc) { + slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME; + slot0 = IWL_MIN_SLOT_TIME; + } + } else if (ctx_pan->vif) { + slot0 = 0; + slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * + ctx_pan->beacon_int; + slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); + + if (test_bit(STATUS_SCAN_HW, &priv->status)) { + slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; + slot1 = IWL_MIN_SLOT_TIME; + } + } + + cmd.slots[0].width = cpu_to_le16(slot0); + cmd.slots[1].width = cpu_to_le16(slot1); + + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC, + sizeof(cmd), &cmd); + if (ret) + IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); + + return ret; +} + /** * iwlagn_commit_rxon - commit staging_rxon to hardware * @@ -345,8 +437,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) /* always get timestamp with Rx frame */ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; - if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) { - struct ieee80211_channel *chan = priv->_agn.hw_roc_channel; + if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->hw_roc_channel) { + struct ieee80211_channel *chan = priv->hw_roc_channel; iwl_set_rxon_channel(priv, chan, ctx); iwl_set_flags_for_band(priv, ctx, chan->band, NULL); @@ -694,8 +786,8 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, - priv->_agn.phy_calib_chain_noise_reset_cmd); - ret = trans_send_cmd_pdu(priv, + priv->phy_calib_chain_noise_reset_cmd); + ret = trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -762,6 +854,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, iwl_wake_any_queue(priv, ctx); } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + + if (ctx->ctxid == IWL_RXON_CTX_BSS) + priv->have_rekey_data = false; } iwlagn_bt_coex_rssi_monitor(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 001622c..37e6240 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -139,6 +139,14 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx return 0; } +/* + * static WEP keys + * + * For each context, the device has a table of 4 static WEP keys + * (one for each key index) that is updated with the following + * commands. + */ + static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, bool send_if_empty) @@ -181,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd.len[0] = cmd_size; if (not_empty || send_if_empty) - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); else return 0; } @@ -232,9 +240,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, return -EINVAL; } - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = HW_KEY_DEFAULT; - priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; + keyconf->hw_key_idx = IWLAGN_HW_KEY_DEFAULT; ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, @@ -247,166 +253,117 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, return ret; } -static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - - key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (keyconf->keylen == WEP_KEY_LEN_128) - key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; - - if (sta_id == ctx->bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; - - memcpy(priv->stations[sta_id].keyinfo.key, - keyconf->key, keyconf->keylen); - - memcpy(&priv->stations[sta_id].sta.key.key[3], - keyconf->key, keyconf->keylen); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ +/* + * dynamic (per-station) keys + * + * The dynamic keys are a little more complicated. The device has + * a key cache of up to STA_KEY_MAX_NUM/STA_KEY_MAX_NUM_PAN keys. + * These are linked to stations by a table that contains an index + * into the key table for each station/key index/{mcast,unicast}, + * i.e. it's basically an array of pointers like this: + * key_offset_t key_mapping[NUM_STATIONS][4][2]; + * (it really works differently, but you can think of it as such) + * + * The key uploading and linking happens in the same command, the + * add station command with STA_MODIFY_KEY_MASK. + */ - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); +static u8 iwlagn_key_sta_id(struct iwl_priv *priv, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + u8 sta_id = IWL_INVALID_STATION; - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + if (sta) + sta_id = iwl_sta_id(sta); - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + /* + * The device expects GTKs for station interfaces to be + * installed as GTKs for the AP station. If we have no + * station ID, then use the ap_sta_id in that case. + */ + if (!sta && vif && vif_priv->ctx) { + switch (vif->type) { + case NL80211_IFTYPE_STATION: + sta_id = vif_priv->ctx->ap_sta_id; + break; + default: + /* + * In all other cases, the key will be + * used either for TX only or is bound + * to a station already. + */ + break; + } + } - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); + return sta_id; } -static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) +static int iwlagn_send_sta_key(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k, + u32 cmd_flags) { unsigned long flags; - __le16 key_flags = 0; + __le16 key_flags; struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (sta_id == ctx->bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + int i; spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, - keyconf->keylen); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, - keyconf->keylen); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); spin_unlock_irqrestore(&priv->sta_lock, flags); - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} - -static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - int ret = 0; - __le16 key_flags = 0; + key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + key_flags |= STA_KEY_FLG_MAP_KEY_MSK; - key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_CCMP: + key_flags |= STA_KEY_FLG_CCMP; + memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen); + break; + case WLAN_CIPHER_SUITE_TKIP: + key_flags |= STA_KEY_FLG_TKIP; + sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32; + for (i = 0; i < 5; i++) + sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]); + memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen); + break; + case WLAN_CIPHER_SUITE_WEP104: + key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; + /* fall through */ + case WLAN_CIPHER_SUITE_WEP40: + key_flags |= STA_KEY_FLG_WEP; + memcpy(&sta_cmd.key.key[3], keyconf->key, keyconf->keylen); + break; + default: + WARN_ON(1); + return -EINVAL; + } - if (sta_id == ctx->bcast_sta_id) + if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) key_flags |= STA_KEY_MULTICAST_MSK; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + /* key pointer (offset) */ + sta_cmd.key.key_offset = keyconf->hw_key_idx; - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = 16; - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; + sta_cmd.key.key_flags = key_flags; + sta_cmd.mode = STA_CONTROL_MODIFY_MSK; + sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; - - /* This copy is acutally not needed: we get the key with each TX */ - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; + return iwl_send_add_sta(priv, &sta_cmd, cmd_flags); } void iwl_update_tkip_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, + struct ieee80211_vif *vif, struct ieee80211_key_conf *keyconf, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) { - u8 sta_id; - unsigned long flags; - int i; + u8 sta_id = iwlagn_key_sta_id(priv, vif, sta); + + if (sta_id == IWL_INVALID_STATION) + return; if (iwl_scan_cancel(priv)) { /* cancel scan failed, just live w/ bad key and rely @@ -414,121 +371,110 @@ void iwl_update_tkip_key(struct iwl_priv *priv, return; } - sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta); - if (sta_id == IWL_INVALID_STATION) - return; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; - - for (i = 0; i < 5; i++) - priv->stations[sta_id].sta.key.tkip_rx_ttak[i] = - cpu_to_le16(phase1key[i]); - - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - + iwlagn_send_sta_key(priv, keyconf, sta_id, + iv32, phase1key, CMD_ASYNC); } int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_key_conf *keyconf, - u8 sta_id) + struct ieee80211_sta *sta) { unsigned long flags; - u16 key_flags; - u8 keyidx; struct iwl_addsta_cmd sta_cmd; + u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta); + + /* if station isn't there, neither is the key */ + if (sta_id == IWL_INVALID_STATION) + return -ENOENT; + + spin_lock_irqsave(&priv->sta_lock, flags); + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); + if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) + sta_id = IWL_INVALID_STATION; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + if (sta_id == IWL_INVALID_STATION) + return 0; lockdep_assert_held(&priv->mutex); ctx->key_mapping_keys--; - spin_lock_irqsave(&priv->sta_lock, flags); - key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); - keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; - IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id); - if (keyconf->keyidx != keyidx) { - /* We need to remove a key with index different that the one - * in the uCode. This means that the key we need to remove has - * been replaced by another one with different index. - * Don't do anything and return ok - */ - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - - if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { - IWL_WARN(priv, "Removing wrong key %d 0x%x\n", - keyconf->keyidx, key_flags); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } + if (!test_and_clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table)) + IWL_ERR(priv, "offset %d not used in uCode key table.\n", + keyconf->hw_key_idx); - if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, - &priv->ucode_key_table)) - IWL_ERR(priv, "index %d not used in uCode key table.\n", - priv->stations[sta_id].sta.key.key_offset); - memset(&priv->stations[sta_id].keyinfo, 0, - sizeof(struct iwl_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, - sizeof(struct iwl_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = - STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); + sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; + sta_cmd.key.key_offset = WEP_INVALID_OFFSET; + sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; + sta_cmd.mode = STA_CONTROL_MODIFY_MSK; return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } -int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, u8 sta_id) +int iwl_set_dynamic_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta) { + struct ieee80211_key_seq seq; + u16 p1k[5]; int ret; + u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta); + const u8 *addr; + + if (sta_id == IWL_INVALID_STATION) + return -EINVAL; lockdep_assert_held(&priv->mutex); + keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); + if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) + return -ENOSPC; + ctx->key_mapping_keys++; - keyconf->hw_key_idx = HW_KEY_DYNAMIC; switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_CCMP: - ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id); - break; case WLAN_CIPHER_SUITE_TKIP: - ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id); + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + + if (sta) + addr = sta->addr; + else /* station mode case only */ + addr = ctx->active.bssid_addr; + + /* pre-fill phase 1 key into device cache */ + ieee80211_get_key_rx_seq(keyconf, 0, &seq); + ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); + ret = iwlagn_send_sta_key(priv, keyconf, sta_id, + seq.tkip.iv32, p1k, CMD_SYNC); break; + case WLAN_CIPHER_SUITE_CCMP: + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + /* fall through */ case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id); + ret = iwlagn_send_sta_key(priv, keyconf, sta_id, + 0, NULL, CMD_SYNC); break; default: - IWL_ERR(priv, - "Unknown alg: %s cipher = %x\n", __func__, - keyconf->cipher); + IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher); ret = -EINVAL; } - IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", + if (ret) { + ctx->key_mapping_keys--; + clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table); + } + + IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n", keyconf->cipher, keyconf->keylen, keyconf->keyidx, - sta_id, ret); + sta ? sta->addr : NULL, ret); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7d3aad8..53bb59e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -39,6 +39,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-agn.h" +#include "iwl-trans.h" /* * mac80211 queues, ACs, hardware queues, FIFOs. @@ -95,132 +96,8 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) return -EINVAL; } -/** - * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array - */ -static void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt) -{ - struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int write_ptr = txq->q.write_ptr; - int txq_id = txq->q.id; - u8 sec_ctl = 0; - u8 sta_id = 0; - u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; - __le16 bc_ent; - - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - - sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; - - switch (sec_ctl & TX_CMD_SEC_MSK) { - case TX_CMD_SEC_CCM: - len += CCMP_MIC_LEN; - break; - case TX_CMD_SEC_TKIP: - len += TKIP_ICV_LEN; - break; - case TX_CMD_SEC_WEP: - len += WEP_IV_LEN + WEP_ICV_LEN; - break; - } - - bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); - - scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; - - if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; -} - -static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int txq_id = txq->q.id; - int read_ptr = txq->q.read_ptr; - u8 sta_id = 0; - __le16 bc_ent; - - WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != priv->cmd_queue) - sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; - - bc_ent = cpu_to_le16(1 | (sta_id << 12)); - scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - - if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; -} - -static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, - u16 txq_id) -{ - u32 tbl_dw_addr; - u32 tbl_dw; - u16 scd_q2ratid; - - scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; - - tbl_dw_addr = priv->scd_base_addr + - IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); - - tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); - - if (txq_id & 0x1) - tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); - else - tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - - iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); - - return 0; -} - -static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) -{ - /* Simply stop the queue, but don't change any configuration; - * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv, - IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); -} - -void iwlagn_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index) -{ - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index); -} - -void iwlagn_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry) -{ - int txq_id = txq->q.id; - int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - - iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), - (active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) | - IWLAGN_SCD_QUEUE_STTS_REG_MSK); - - txq->sched_retry = scd_retry; - - IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", - active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); -} - -static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid) +static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, + int tid) { if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + @@ -237,108 +114,6 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); } -void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, - struct ieee80211_sta *sta, - int tid, int frame_limit) -{ - int sta_id, tx_fifo, txq_id, ssn_idx; - u16 ra_tid; - unsigned long flags; - struct iwl_tid_data *tid_data; - - sta_id = iwl_sta_id(sta); - if (WARN_ON(sta_id == IWL_INVALID_STATION)) - return; - if (WARN_ON(tid >= MAX_TID_COUNT)) - return; - - spin_lock_irqsave(&priv->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; - ssn_idx = SEQ_TO_SN(tid_data->seq_number); - txq_id = tid_data->agg.txq_id; - tx_fifo = tid_data->agg.tx_fifo; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - ra_tid = BUILD_RAxTID(sta_id, tid); - - spin_lock_irqsave(&priv->lock, flags); - - /* Stop this Tx queue before configuring it */ - iwlagn_tx_queue_stop_scheduler(priv, txq_id); - - /* Map receiver-address / traffic-ID to this queue */ - iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); - - /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<<txq_id)); - - /* enable aggregations for the queue */ - iwl_set_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1<<txq_id)); - - /* Place first TFD at index corresponding to start sequence number. - * Assumes that ssn_idx is valid (!= 0xFFF) */ - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); - - /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + - sizeof(u32), - ((frame_limit << - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((frame_limit << - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - - iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); - - /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) -{ - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || - (IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { - IWL_ERR(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWLAGN_FIRST_AMPDU_QUEUE, - IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues - 1); - return -EINVAL; - } - - iwlagn_tx_queue_stop_scheduler(priv, txq_id); - - iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id)); - - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); - - iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv, txq_id); - iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - - return 0; -} - -/* - * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->lock and mac access - */ -void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) -{ - iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); -} - static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, struct ieee80211_tx_info *info, __le16 fc, __le32 *tx_flags) @@ -363,19 +138,15 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, __le32 tx_flags = tx_cmd->tx_flags; tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) tx_flags |= TX_CMD_FLG_ACK_MSK; - if (ieee80211_is_mgmt(fc)) - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - if (ieee80211_is_probe_resp(fc) && - !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) - tx_flags |= TX_CMD_FLG_TSF_MSK; - } else { - tx_flags &= (~TX_CMD_FLG_ACK_MSK); - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } + else + tx_flags &= ~TX_CMD_FLG_ACK_MSK; - if (ieee80211_is_back_req(fc)) + if (ieee80211_is_probe_resp(fc)) + tx_flags |= TX_CMD_FLG_TSF_MSK; + else if (ieee80211_is_back_req(fc)) tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; else if (info->band == IEEE80211_BAND_2GHZ && priv->cfg->bt_params && @@ -446,6 +217,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, if (ieee80211_is_data(fc)) { tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL if (priv->tm_fixed_rate) { /* * rate overwrite by testmode @@ -456,6 +228,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate, sizeof(tx_cmd->rate_n_flags)); } +#endif return; } @@ -547,26 +320,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; struct iwl_station_priv *sta_priv = NULL; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_device_cmd *out_cmd; - struct iwl_cmd_meta *out_meta; - struct iwl_tx_cmd *tx_cmd; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct iwl_tx_cmd *tx_cmd; int txq_id; - dma_addr_t phys_addr = 0; - dma_addr_t txcmd_phys; - dma_addr_t scratch_phys; - u16 len, firstlen, secondlen; + u16 seq_number = 0; __le16 fc; u8 hdr_len; + u16 len; u8 sta_id; - u8 wait_write_ptr = 0; u8 tid = 0; - u8 *qc = NULL; unsigned long flags; bool is_agg = false; @@ -614,8 +378,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); - if (sta) - sta_priv = (void *)sta->drv_priv; + if (info->control.sta) + sta_priv = (void *)info->control.sta->drv_priv; if (sta_priv && sta_priv->asleep && (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { @@ -650,6 +414,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock(&priv->sta_lock); if (ieee80211_is_data_qos(fc)) { + u8 *qc = NULL; qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; @@ -670,38 +435,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } } - txq = &priv->txq[txq_id]; - q = &txq->q; - - if (unlikely(iwl_queue_space(q) < q->high_mark)) + tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id); + if (unlikely(!tx_cmd)) goto drop_unlock_sta; - /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb = skb; - txq->txb[q->write_ptr].ctx = ctx; - - /* Set up first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = txq->cmd[q->write_ptr]; - out_meta = &txq->meta[q->write_ptr]; - tx_cmd = &out_cmd->cmd.tx; - memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); - memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); - - /* - * Set up the Tx-command (not MAC!) header. - * Store the chosen Tx queue and TFD index within the sequence field; - * after Tx, uCode's Tx response will return this value so driver can - * locate the frame within the tx queue and do post-tx processing. - */ - out_cmd->hdr.cmd = REPLY_TX; - out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); - /* Copy MAC header from skb into command buffer */ memcpy(tx_cmd->hdr, hdr, hdr_len); - /* Total # bytes to be transmitted */ len = (u16)skb->len; tx_cmd->len = cpu_to_le16(len); @@ -716,54 +456,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); iwl_update_stats(priv, true, fc, len); - /* - * Use the first empty entry in this queue's command buffer array - * to contain the Tx command and MAC header concatenated together - * (payload data will be in another buffer). - * Size of this varies, due to varying MAC header length. - * If end is not dword aligned, we'll have 2 extra bytes at the end - * of the MAC header (device reads on dword boundaries). - * We'll tell device about this padding later. - */ - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - firstlen = (len + 3) & ~3; - - /* Tell NIC about any 2-byte padding after MAC header */ - if (firstlen != len) - tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; - - /* Physical address of this Tx command's header (not MAC header!), - * within command buffer array. */ - txcmd_phys = dma_map_single(priv->bus.dev, - &out_cmd->hdr, firstlen, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(priv->bus.dev, txcmd_phys))) - goto drop_unlock_sta; - dma_unmap_addr_set(out_meta, mapping, txcmd_phys); - dma_unmap_len_set(out_meta, len, firstlen); - - if (!ieee80211_has_morefrags(hdr->frame_control)) { - txq->need_update = 1; - } else { - wait_write_ptr = 1; - txq->need_update = 0; - } - /* Set up TFD's 2nd entry to point directly to remainder of skb, - * if any (802.11 null frames have no payload). */ - secondlen = skb->len - hdr_len; - if (secondlen > 0) { - phys_addr = dma_map_single(priv->bus.dev, skb->data + hdr_len, - secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) { - dma_unmap_single(priv->bus.dev, - dma_unmap_addr(out_meta, mapping), - dma_unmap_len(out_meta, len), - DMA_BIDIRECTIONAL); - goto drop_unlock_sta; - } - } + if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx)) + goto drop_unlock_sta; if (ieee80211_is_data_qos(fc)) { priv->stations[sta_id].tid[tid].tfds_in_queue++; @@ -772,55 +467,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } spin_unlock(&priv->sta_lock); - - /* Attach buffers to TFD */ - iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); - if (secondlen > 0) - iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, - secondlen, 0); - - scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + - offsetof(struct iwl_tx_cmd, scratch); - - /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(priv->bus.dev, txcmd_phys, firstlen, - DMA_BIDIRECTIONAL); - tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); - tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - - IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", - le16_to_cpu(out_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); - - /* Set up entry for this TFD in Tx byte-count array */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) - iwlagn_txq_update_byte_cnt_tbl(priv, txq, - le16_to_cpu(tx_cmd->len)); - - dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen, - DMA_BIDIRECTIONAL); - - trace_iwlwifi_dev_tx(priv, - &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], - sizeof(struct iwl_tfd), - &out_cmd->hdr, firstlen, - skb->data + hdr_len, secondlen); - - /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); /* - * At this point the frame is "transmitted" successfully - * and we will get a TX status notification eventually, - * regardless of the value of ret. "ret" only indicates - * whether or not we should update the write pointer. - */ - - /* * Avoid atomic ops if it isn't an associated client. * Also, if this is a packet for aggregation, don't * increase the counter because the ucode will stop @@ -830,17 +479,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta_priv && sta_priv->client && !is_agg) atomic_inc(&sta_priv->pending_frames); - if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { - if (wait_write_ptr) { - spin_lock_irqsave(&priv->lock, flags); - txq->need_update = 1; - iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - } else { - iwl_stop_queue(priv, txq); - } - } - return 0; drop_unlock_sta: @@ -997,7 +635,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); + trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -1026,7 +664,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo); + trans_txq_agg_disable(&priv->trans, txq_id, + ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 06304a6..a895a09 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -41,38 +41,6 @@ #include "iwl-agn-calib.h" #include "iwl-trans.h" -#define IWL_AC_UNSET -1 - -struct queue_to_fifo_ac { - s8 fifo, ac; -}; - -static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, -}; - -static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_BE_IPAN, 2, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, -}; - static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 0, COEX_UNASSOC_IDLE_FLAGS}, @@ -199,12 +167,12 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); - cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]); + memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(offset_calib)); if (!(cmd.radio_sensor_offset)) cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", - cmd.radio_sensor_offset); + le16_to_cpu(cmd.radio_sensor_offset)); return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], (u8 *)&cmd, sizeof(cmd)); } @@ -222,9 +190,10 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.flags = + IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -322,7 +291,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return trans_send_cmd_pdu(priv, + return trans_send_cmd_pdu(&priv->trans, COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -355,7 +324,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, sizeof(iwlagn_bt_prio_tbl)); - if (trans_send_cmd_pdu(priv, + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) IWL_ERR(priv, "failed to send BT prio tbl command\n"); @@ -368,7 +337,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) env_cmd.action = action; env_cmd.type = type; - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) @@ -379,111 +348,9 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) static int iwlagn_alive_notify(struct iwl_priv *priv) { - const struct queue_to_fifo_ac *queue_to_fifo; - struct iwl_rxon_context *ctx; - u32 a; - unsigned long flags; - int i, chan; - u32 reg_val; int ret; - spin_lock_irqsave(&priv->lock, flags); - - priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND; - /* reset conext data memory */ - for (; a < priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND; - a += 4) - iwl_write_targ_mem(priv, a, 0); - /* reset tx status memory */ - for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND; - a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + - IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) - iwl_write_targ_mem(priv, a, 0); - - iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR, - priv->scd_bc_tbls.dma >> 10); - - /* Enable DMA channel */ - for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); - - /* Update FH chicken bits */ - reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - - iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, - IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)); - iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); - - /* initiate the queues */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { - iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) + - sizeof(u32), - ((SCD_WIN_SIZE << - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - } - - iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, - IWL_MASK(0, priv->hw_params.max_txq_num)); - - /* Activate all Tx DMA/FIFO channels */ - iwlagn_txq_set_sched(priv, IWL_MASK(0, 7)); - - /* map queues to FIFOs */ - if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) - queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; - else - queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - - iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); - - /* make sure all queue are not stopped */ - memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); - for (i = 0; i < 4; i++) - atomic_set(&priv->queue_stop_count[i], 0); - for_each_context(priv, ctx) - ctx->last_tx_rejected = false; - - /* reset to 0 to enable all the queue first */ - priv->txq_ctx_active_msk = 0; - - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); - - for (i = 0; i < 10; i++) { - int fifo = queue_to_fifo[i].fifo; - int ac = queue_to_fifo[i].ac; - - iwl_txq_ctx_activate(priv, i); - - if (fifo == IWL_TX_FIFO_UNUSED) - continue; - - if (ac != IWL_AC_UNSET) - iwl_set_swq_id(&priv->txq[i], ac, i); - iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Enable L1-Active */ - iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + trans_tx_start(&priv->trans); ret = iwlagn_send_wimax_coex(priv); if (ret) @@ -611,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwlagn_ucode_type old_type; - ret = iwlagn_start_device(priv); + ret = trans_start_device(&priv->trans); if (ret) return ret; @@ -628,8 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; } - /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); + trans_kick_nic(&priv->trans); /* * Some things may run in the background now, but we @@ -647,14 +513,21 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return -EIO; } - ret = iwl_verify_ucode(priv, image); - if (ret) { - priv->ucode_type = old_type; - return ret; - } + /* + * This step takes a long time (60-80ms!!) and + * WoWLAN image should be loaded quickly, so + * skip it for WoWLAN. + */ + if (ucode_type != IWL_UCODE_WOWLAN) { + ret = iwl_verify_ucode(priv, image); + if (ret) { + priv->ucode_type = old_type; + return ret; + } - /* delay a bit to give rfkill time to run */ - msleep(5); + /* delay a bit to give rfkill time to run */ + msleep(5); + } ret = iwlagn_alive_notify(priv); if (ret) { @@ -707,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ - iwlagn_stop_device(priv); + trans_stop_device(&priv->trans); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 38a1e4f..4b666b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -26,9 +26,6 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -55,7 +52,7 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-pci.h" +#include "iwl-bus.h" #include "iwl-trans.h" /****************************************************************************** @@ -206,7 +203,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) cmd.data[1] = priv->beacon_skb->data; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -375,7 +372,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) u32 next_entry; /* index of next entry to be written by uCode */ base = priv->device_pointers.error_event_table; - if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + if (iwlagn_hw_valid_rtc_data_addr(base)) { capacity = iwl_read_targ_mem(priv, base); num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); @@ -457,380 +454,6 @@ static void iwl_bg_tx_flush(struct work_struct *work) iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); } -/** - * iwl_rx_handle - Main entry function for receiving responses from uCode - * - * Uses the priv->rx_handlers callback function array to invoke - * the appropriate handlers, including command responses, - * frame-received notifications, and other notifications. - */ -static void iwl_rx_handle(struct iwl_priv *priv) -{ - struct iwl_rx_mem_buffer *rxb; - struct iwl_rx_packet *pkt; - struct iwl_rx_queue *rxq = &priv->rxq; - u32 r, i; - int reclaim; - unsigned long flags; - u8 fill_rx = 0; - u32 count = 8; - int total_empty; - - /* uCode's read index (stored in shared DRAM) indicates the last Rx - * buffer that the driver may process (last buffer filled by ucode). */ - r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; - i = rxq->read; - - /* Rx interrupt, but nothing sent from uCode */ - if (i == r) - IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); - - /* calculate total frames need to be restock after handling RX */ - total_empty = r - rxq->write_actual; - if (total_empty < 0) - total_empty += RX_QUEUE_SIZE; - - if (total_empty > (RX_QUEUE_SIZE / 2)) - fill_rx = 1; - - while (i != r) { - int len; - - rxb = rxq->queue[i]; - - /* If an RXB doesn't have a Rx queue slot associated with it, - * then a bug has been introduced in the queue refilling - * routines -- catch it here */ - if (WARN_ON(rxb == NULL)) { - i = (i + 1) & RX_QUEUE_MASK; - continue; - } - - rxq->queue[i] = NULL; - - dma_unmap_page(priv->bus.dev, rxb->page_dma, - PAGE_SIZE << priv->hw_params.rx_page_order, - DMA_FROM_DEVICE); - pkt = rxb_addr(rxb); - - len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - len += sizeof(u32); /* account for status word */ - trace_iwlwifi_dev_rx(priv, pkt, len); - - /* Reclaim a command buffer only if this packet is a response - * to a (driver-originated) command. - * If the packet (e.g. Rx frame) originated from uCode, - * there is no command buffer to reclaim. - * Ucode should set SEQ_RX_FRAME bit if ucode-originated, - * but apparently a few don't get set; catch them here. */ - reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && - (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && - (pkt->hdr.cmd != REPLY_RX) && - (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && - (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && - (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && - (pkt->hdr.cmd != REPLY_TX); - - /* - * Do the notification wait before RX handlers so - * even if the RX handler consumes the RXB we have - * access to it in the notification wait entry. - */ - if (!list_empty(&priv->_agn.notif_waits)) { - struct iwl_notification_wait *w; - - spin_lock(&priv->_agn.notif_wait_lock); - list_for_each_entry(w, &priv->_agn.notif_waits, list) { - if (w->cmd == pkt->hdr.cmd) { - w->triggered = true; - if (w->fn) - w->fn(priv, pkt, w->fn_data); - } - } - spin_unlock(&priv->_agn.notif_wait_lock); - - wake_up_all(&priv->_agn.notif_waitq); - } - if (priv->pre_rx_handler) - priv->pre_rx_handler(priv, rxb); - - /* Based on type of command response or notification, - * handle those that need handling via function in - * rx_handlers table. See iwl_setup_rx_handlers() */ - if (priv->rx_handlers[pkt->hdr.cmd]) { - IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, - i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); - priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; - priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); - } else { - /* No handling needed */ - IWL_DEBUG_RX(priv, - "r %d i %d No handler needed for %s, 0x%02x\n", - r, i, get_cmd_string(pkt->hdr.cmd), - pkt->hdr.cmd); - } - - /* - * XXX: After here, we should always check rxb->page - * against NULL before touching it or its virtual - * memory (pkt). Because some rx_handler might have - * already taken or freed the pages. - */ - - if (reclaim) { - /* Invoke any callbacks, transfer the buffer to caller, - * and fire off the (possibly) blocking - * trans_send_cmd() - * as we reclaim the driver command queue */ - if (rxb->page) - iwl_tx_cmd_complete(priv, rxb); - else - IWL_WARN(priv, "Claim null rxb?\n"); - } - - /* Reuse the page if possible. For notification packets and - * SKBs that fail to Rx correctly, add them back into the - * rx_free list for reuse later. */ - spin_lock_irqsave(&rxq->lock, flags); - if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page, - 0, PAGE_SIZE << priv->hw_params.rx_page_order, - DMA_FROM_DEVICE); - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - } else - list_add_tail(&rxb->list, &rxq->rx_used); - - spin_unlock_irqrestore(&rxq->lock, flags); - - i = (i + 1) & RX_QUEUE_MASK; - /* If there are a lot of unused frames, - * restock the Rx queue so ucode wont assert. */ - if (fill_rx) { - count++; - if (count >= 8) { - rxq->read = i; - iwlagn_rx_replenish_now(priv); - count = 0; - } - } - } - - /* Backtrack one entry */ - rxq->read = i; - if (fill_rx) - iwlagn_rx_replenish_now(priv); - else - iwlagn_rx_queue_restock(priv); -} - -/* tasklet for iwlagn interrupt */ -static void iwl_irq_tasklet(struct iwl_priv *priv) -{ - u32 inta = 0; - u32 handled = 0; - unsigned long flags; - u32 i; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_mask; -#endif - - spin_lock_irqsave(&priv->lock, flags); - - /* Ack/clear/reset pending uCode interrupts. - * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, - */ - /* There is a hardware bug in the interrupt mask function that some - * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if - * they are disabled in the CSR_INT_MASK register. Furthermore the - * ICT interrupt handling mechanism has another bug that might cause - * these unmasked interrupts fail to be detected. We workaround the - * hardware bugs here by ACKing all the possible interrupts so that - * interrupt coalescing can still be achieved. - */ - iwl_write32(priv, CSR_INT, priv->_agn.inta | ~priv->inta_mask); - - inta = priv->_agn.inta; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_ISR) { - /* just for debug */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", - inta, inta_mask); - } -#endif - - spin_unlock_irqrestore(&priv->lock, flags); - - /* saved interrupt in inta variable now we can reset priv->_agn.inta */ - priv->_agn.inta = 0; - - /* Now service all interrupt bits discovered above. */ - if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Hardware error detected. Restarting.\n"); - - /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(priv); - - priv->isr_stats.hw++; - iwl_irq_handle_error(priv); - - handled |= CSR_INT_BIT_HW_ERR; - - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " - "the frame/frames.\n"); - priv->isr_stats.sch++; - } - - /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(priv, "Alive interrupt\n"); - priv->isr_stats.alive++; - } - } -#endif - /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); - - /* HW RF KILL switch toggled */ - if (inta & CSR_INT_BIT_RF_KILL) { - int hw_rf_kill = 0; - if (!(iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rf_kill = 1; - - IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", - hw_rf_kill ? "disable radio" : "enable radio"); - - priv->isr_stats.rfkill++; - - /* driver only loads ucode once setting the interface up. - * the driver allows loading the ucode even if the radio - * is killed. Hence update the killswitch state here. The - * rfkill handler will care about restarting if needed. - */ - if (!test_bit(STATUS_ALIVE, &priv->status)) { - if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, &priv->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->status); - wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); - } - - handled |= CSR_INT_BIT_RF_KILL; - } - - /* Chip got too hot and stopped itself */ - if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(priv, "Microcode CT kill error detected.\n"); - priv->isr_stats.ctkill++; - handled |= CSR_INT_BIT_CT_KILL; - } - - /* Error detected by uCode */ - if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(priv, "Microcode SW error detected. " - " Restarting 0x%X.\n", inta); - priv->isr_stats.sw++; - iwl_irq_handle_error(priv); - handled |= CSR_INT_BIT_SW_ERR; - } - - /* uCode wakes up after power-down sleep */ - if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - for (i = 0; i < priv->hw_params.max_txq_num; i++) - iwl_txq_update_write_ptr(priv, &priv->txq[i]); - - priv->isr_stats.wakeup++; - - handled |= CSR_INT_BIT_WAKEUP; - } - - /* All uCode command responses, including Tx command responses, - * Rx "responses" (frame-received notification), and other - * notifications from uCode come through here*/ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | - CSR_INT_BIT_RX_PERIODIC)) { - IWL_DEBUG_ISR(priv, "Rx interrupt\n"); - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { - handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(priv, CSR_FH_INT_STATUS, - CSR_FH_INT_RX_MASK); - } - if (inta & CSR_INT_BIT_RX_PERIODIC) { - handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); - } - /* Sending RX interrupt require many steps to be done in the - * the device: - * 1- write interrupt to current index in ICT table. - * 2- dma RX frame. - * 3- update RX shared data to indicate last write index. - * 4- send interrupt. - * This could lead to RX race, driver could receive RX interrupt - * but the shared data changes does not reflect this; - * periodic interrupt will detect any dangling Rx activity. - */ - - /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(priv, CSR_INT_PERIODIC_REG, - CSR_INT_PERIODIC_DIS); - iwl_rx_handle(priv); - - /* - * Enable periodic interrupt in 8 msec only if we received - * real RX interrupt (instead of just periodic int), to catch - * any dangling Rx interrupt. If it was just the periodic - * interrupt, there was no dangling Rx activity, and no need - * to extend the periodic interrupt; one-shot is enough. - */ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(priv, CSR_INT_PERIODIC_REG, - CSR_INT_PERIODIC_ENA); - - priv->isr_stats.rx++; - } - - /* This "Tx" DMA channel is used only for loading uCode */ - if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); - IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); - priv->isr_stats.tx++; - handled |= CSR_INT_BIT_FH_TX; - /* Wake up uCode load routine, now that load is complete */ - priv->ucode_write_complete = 1; - wake_up_interruptible(&priv->wait_command_queue); - } - - if (inta & ~handled) { - IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv->isr_stats.unhandled++; - } - - if (inta & ~(priv->inta_mask)) { - IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~priv->inta_mask); - } - - /* Re-enable all interrupts */ - /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - /* Re-enable RF_KILL if it occurred */ - else if (handled & CSR_INT_BIT_RF_KILL) - iwl_enable_rfkill_int(priv); -} - /***************************************************************************** * * sysfs attributes @@ -954,7 +577,7 @@ static struct attribute_group iwl_attribute_group = { static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc) { if (desc->v_addr) - dma_free_coherent(priv->bus.dev, desc->len, + dma_free_coherent(priv->bus->dev, desc->len, desc->v_addr, desc->p_addr); desc->v_addr = NULL; desc->len = 0; @@ -970,6 +593,7 @@ static void iwl_dealloc_ucode(struct iwl_priv *priv) { iwl_free_fw_img(priv, &priv->ucode_rt); iwl_free_fw_img(priv, &priv->ucode_init); + iwl_free_fw_img(priv, &priv->ucode_wowlan); } static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, @@ -980,7 +604,7 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, return -EINVAL; } - desc->v_addr = dma_alloc_coherent(priv->bus.dev, len, + desc->v_addr = dma_alloc_coherent(priv->bus->dev, len, &desc->p_addr, GFP_KERNEL); if (!desc->v_addr) return -ENOMEM; @@ -1034,13 +658,14 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) priv->firmware_name); return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, - priv->bus.dev, + priv->bus->dev, GFP_KERNEL, priv, iwl_ucode_callback); } struct iwlagn_firmware_pieces { - const void *inst, *data, *init, *init_data; - size_t inst_size, data_size, init_size, init_data_size; + const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; + size_t inst_size, data_size, init_size, init_data_size, + wowlan_inst_size, wowlan_data_size; u32 build; @@ -1279,6 +904,14 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, goto invalid_tlv_len; priv->enhance_sensitivity_table = true; break; + case IWL_UCODE_TLV_WOWLAN_INST: + pieces->wowlan_inst = tlv_data; + pieces->wowlan_inst_size = tlv_len; + break; + case IWL_UCODE_TLV_WOWLAN_DATA: + pieces->wowlan_data = tlv_data; + pieces->wowlan_data_size = tlv_len; + break; case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: if (tlv_len != sizeof(u32)) goto invalid_tlv_len; @@ -1473,6 +1106,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto err_pci_alloc; } + /* WoWLAN instructions and data */ + if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { + if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.code, + pieces.wowlan_inst, + pieces.wowlan_inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.data, + pieces.wowlan_data, + pieces.wowlan_data_size)) + goto err_pci_alloc; + } + /* Now that we can no longer fail, copy information */ /* @@ -1480,20 +1125,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * for each event, which is of mode 1 (including timestamp) for all * new microcodes that include this information. */ - priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; + priv->init_evtlog_ptr = pieces.init_evtlog_ptr; if (pieces.init_evtlog_size) - priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; + priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; else - priv->_agn.init_evtlog_size = + priv->init_evtlog_size = priv->cfg->base_params->max_event_log_size; - priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; - priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; + priv->init_errlog_ptr = pieces.init_errlog_ptr; + priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr; if (pieces.inst_evtlog_size) - priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; + priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; else - priv->_agn.inst_evtlog_size = + priv->inst_evtlog_size = priv->cfg->base_params->max_event_log_size; - priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; + priv->inst_errlog_ptr = pieces.inst_errlog_ptr; priv->new_scan_threshold_behaviour = !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); @@ -1519,9 +1164,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) ucode_capa.standard_phy_calibration_size = IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; - priv->_agn.phy_calib_chain_noise_reset_cmd = + priv->phy_calib_chain_noise_reset_cmd = ucode_capa.standard_phy_calibration_size; - priv->_agn.phy_calib_chain_noise_gain_cmd = + priv->phy_calib_chain_noise_gain_cmd = ucode_capa.standard_phy_calibration_size + 1; /************************************************** @@ -1537,7 +1182,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (err) IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - err = sysfs_create_group(&(priv->bus.dev->kobj), + err = sysfs_create_group(&(priv->bus->dev->kobj), &iwl_attribute_group); if (err) { IWL_ERR(priv, "failed to create sysfs device attributes\n"); @@ -1546,7 +1191,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); - complete(&priv->_agn.firmware_loading_complete); + complete(&priv->firmware_loading_complete); return; try_again: @@ -1560,8 +1205,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) IWL_ERR(priv, "failed to allocate pci memory\n"); iwl_dealloc_ucode(priv); out_unbind: - complete(&priv->_agn.firmware_loading_complete); - device_release_driver(priv->bus.dev); + complete(&priv->firmware_loading_complete); + device_release_driver(priv->bus->dev); release_firmware(ucode_raw); } @@ -1642,13 +1287,13 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) base = priv->device_pointers.error_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { if (!base) - base = priv->_agn.init_errlog_ptr; + base = priv->init_errlog_ptr; } else { if (!base) - base = priv->_agn.inst_errlog_ptr; + base = priv->inst_errlog_ptr; } - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + if (!iwlagn_hw_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Not valid error log pointer 0x%08X for %s uCode\n", base, @@ -1718,10 +1363,10 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, base = priv->device_pointers.log_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { if (!base) - base = priv->_agn.init_evtlog_ptr; + base = priv->init_evtlog_ptr; } else { if (!base) - base = priv->_agn.inst_evtlog_ptr; + base = priv->inst_evtlog_ptr; } if (mode == 0) @@ -1830,16 +1475,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, base = priv->device_pointers.log_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { - logsize = priv->_agn.init_evtlog_size; + logsize = priv->init_evtlog_size; if (!base) - base = priv->_agn.init_evtlog_ptr; + base = priv->init_evtlog_ptr; } else { - logsize = priv->_agn.inst_evtlog_size; + logsize = priv->inst_evtlog_size; if (!base) - base = priv->_agn.inst_evtlog_ptr; + base = priv->inst_evtlog_ptr; } - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + if (!iwlagn_hw_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Invalid event log pointer 0x%08X for %s uCode\n", base, @@ -1942,7 +1587,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) adv_cmd.critical_temperature_exit = cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(adv_cmd), &adv_cmd); if (ret) @@ -1958,7 +1603,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) cmd.critical_temperature_R = cpu_to_le32(priv->hw_params.ct_kill_threshold); - ret = trans_send_cmd_pdu(priv, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -1984,10 +1629,29 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } +static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) +{ + struct iwl_tx_ant_config_cmd tx_ant_cmd = { + .valid = cpu_to_le32(valid_tx_ant), + }; + + if (IWL_UCODE_API(priv->ucode_ver) > 1) { + IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); + return trans_send_cmd_pdu(&priv->trans, + TX_ANT_CONFIGURATION_CMD, + CMD_SYNC, + sizeof(struct iwl_tx_ant_config_cmd), + &tx_ant_cmd); + } else { + IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); + return -EOPNOTSUPP; + } +} + /** * iwl_alive_start - called after REPLY_ALIVE notification received * from protocol/runtime uCode (initialization uCode's @@ -1998,6 +1662,7 @@ int iwl_alive_start(struct iwl_priv *priv) int ret = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + /*TODO: this should go to the transport layer */ iwl_reset_ict(priv); IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); @@ -2055,7 +1720,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Configure Tx antenna selection based on H/W config */ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); - if (iwl_is_associated_ctx(ctx)) { + if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ @@ -2070,7 +1735,10 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_set_rxon_chain(priv, ctx); } - iwl_reset_run_time_calib(priv); + if (!priv->wowlan) { + /* WoWLAN ucode will not reply in the same way, skip it */ + iwl_reset_run_time_calib(priv); + } set_bit(STATUS_READY, &priv->status); @@ -2137,7 +1805,7 @@ static void __iwl_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - iwlagn_stop_device(priv); + trans_stop_device(&priv->trans); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -2152,55 +1820,6 @@ static void iwl_down(struct iwl_priv *priv) iwl_cancel_deferred_work(priv); } -#define HW_READY_TIMEOUT (50) - -/* Note: returns poll_bit return value, which is >= 0 if success */ -static int iwl_set_hw_ready(struct iwl_priv *priv) -{ - int ret; - - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); - - /* See if we got it */ - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - HW_READY_TIMEOUT); - - IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); - return ret; -} - -/* Note: returns standard 0/-ERROR code */ -int iwl_prepare_card_hw(struct iwl_priv *priv) -{ - int ret; - - IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); - - ret = iwl_set_hw_ready(priv); - if (ret >= 0) - return 0; - - /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PREPARE); - - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, - CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); - - if (ret < 0) - return ret; - - /* HW should be ready by now, check again. */ - ret = iwl_set_hw_ready(priv); - if (ret >= 0) - return 0; - return ret; -} - #define MAX_HW_RESTARTS 5 static int __iwl_up(struct iwl_priv *priv) @@ -2336,19 +1955,6 @@ static void iwl_bg_restart(struct work_struct *data) } } -static void iwl_bg_rx_replenish(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, rx_replenish); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - iwlagn_rx_replenish(priv); - mutex_unlock(&priv->mutex); -} - static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, @@ -2383,7 +1989,7 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb, /* TODO: queue up if scanning? */ if (test_bit(STATUS_SCANNING, &priv->status) || - priv->_agn.offchan_tx_skb) { + priv->offchan_tx_skb) { ret = -EBUSY; goto out; } @@ -2397,14 +2003,14 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb, goto out; } - priv->_agn.offchan_tx_skb = skb; - priv->_agn.offchan_tx_timeout = wait; - priv->_agn.offchan_tx_chan = chan; + priv->offchan_tx_skb = skb; + priv->offchan_tx_timeout = wait; + priv->offchan_tx_chan = chan; ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif, IWL_SCAN_OFFCH_TX, chan->band); if (ret) - priv->_agn.offchan_tx_skb = NULL; + priv->offchan_tx_skb = NULL; out: mutex_unlock(&priv->mutex); free: @@ -2421,12 +2027,12 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); - if (!priv->_agn.offchan_tx_skb) { + if (!priv->offchan_tx_skb) { ret = -EINVAL; goto unlock; } - priv->_agn.offchan_tx_skb = NULL; + priv->offchan_tx_skb = NULL; ret = iwl_scan_cancel_timeout(priv, 200); if (ret) @@ -2572,6 +2178,23 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; + if (priv->ucode_wowlan.code.len && device_can_wakeup(priv->bus->dev)) { + hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_RFKILL_RELEASE; + if (!iwlagn_mod_params.sw_crypto) + hw->wiphy->wowlan.flags |= + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE; + + hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS; + hw->wiphy->wowlan.pattern_min_len = + IWLAGN_WOWLAN_MIN_PATTERN_LEN; + hw->wiphy->wowlan.pattern_max_len = + IWLAGN_WOWLAN_MAX_PATTERN_LEN; + } + if (iwlagn_mod_params.power_save) hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; else @@ -2656,6 +2279,467 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "leave\n"); } +static int iwlagn_send_patterns(struct iwl_priv *priv, + struct cfg80211_wowlan *wowlan) +{ + struct iwlagn_wowlan_patterns_cmd *pattern_cmd; + struct iwl_host_cmd cmd = { + .id = REPLY_WOWLAN_PATTERNS, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + .flags = CMD_SYNC, + }; + int i, err; + + if (!wowlan->n_patterns) + return 0; + + cmd.len[0] = sizeof(*pattern_cmd) + + wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern); + + pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); + if (!pattern_cmd) + return -ENOMEM; + + pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns); + + for (i = 0; i < wowlan->n_patterns; i++) { + int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); + + memcpy(&pattern_cmd->patterns[i].mask, + wowlan->patterns[i].mask, mask_len); + memcpy(&pattern_cmd->patterns[i].pattern, + wowlan->patterns[i].pattern, + wowlan->patterns[i].pattern_len); + pattern_cmd->patterns[i].mask_size = mask_len; + pattern_cmd->patterns[i].pattern_size = + wowlan->patterns[i].pattern_len; + } + + cmd.data[0] = pattern_cmd; + err = trans_send_cmd(&priv->trans, &cmd); + kfree(pattern_cmd); + return err; +} + +static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_gtk_rekey_data *data) +{ + struct iwl_priv *priv = hw->priv; + + if (iwlagn_mod_params.sw_crypto) + return; + + mutex_lock(&priv->mutex); + + if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) + goto out; + + memcpy(priv->kek, data->kek, NL80211_KEK_LEN); + memcpy(priv->kck, data->kck, NL80211_KCK_LEN); + priv->replay_ctr = cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr)); + priv->have_rekey_data = true; + + out: + mutex_unlock(&priv->mutex); +} + +struct wowlan_key_data { + struct iwl_rxon_context *ctx; + struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc; + struct iwlagn_wowlan_tkip_params_cmd *tkip; + const u8 *bssid; + bool error, use_rsc_tsc, use_tkip; +}; + +static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) +{ + int i; + + for (i = 0; i < IWLAGN_P1K_SIZE; i++) + out[i] = cpu_to_le16(p1k[i]); +} + +static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *_data) +{ + struct iwl_priv *priv = hw->priv; + struct wowlan_key_data *data = _data; + struct iwl_rxon_context *ctx = data->ctx; + struct aes_sc *aes_sc, *aes_tx_sc = NULL; + struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL; + struct iwlagn_p1k_cache *rx_p1ks; + u8 *rx_mic_key; + struct ieee80211_key_seq seq; + u32 cur_rx_iv32 = 0; + u16 p1k[IWLAGN_P1K_SIZE]; + int ret, i; + + mutex_lock(&priv->mutex); + + if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) && + !sta && !ctx->key_mapping_keys) + ret = iwl_set_default_wep_key(priv, ctx, key); + else + ret = iwl_set_dynamic_key(priv, ctx, key, sta); + + if (ret) { + IWL_ERR(priv, "Error setting key during suspend!\n"); + data->error = true; + } + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + if (sta) { + tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; + tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc; + + rx_p1ks = data->tkip->rx_uni; + + ieee80211_get_key_tx_seq(key, &seq); + tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16); + tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32); + + ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k); + iwlagn_convert_p1k(p1k, data->tkip->tx.p1k); + + memcpy(data->tkip->mic_keys.tx, + &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], + IWLAGN_MIC_KEY_SIZE); + + rx_mic_key = data->tkip->mic_keys.rx_unicast; + } else { + tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc; + rx_p1ks = data->tkip->rx_multi; + rx_mic_key = data->tkip->mic_keys.rx_mcast; + } + + /* + * For non-QoS this relies on the fact that both the uCode and + * mac80211 use TID 0 (as they need to to avoid replay attacks) + * for checking the IV in the frames. + */ + for (i = 0; i < IWLAGN_NUM_RSC; i++) { + ieee80211_get_key_rx_seq(key, i, &seq); + tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16); + tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32); + /* wrapping isn't allowed, AP must rekey */ + if (seq.tkip.iv32 > cur_rx_iv32) + cur_rx_iv32 = seq.tkip.iv32; + } + + ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k); + iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k); + ieee80211_get_tkip_rx_p1k(key, data->bssid, + cur_rx_iv32 + 1, p1k); + iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k); + + memcpy(rx_mic_key, + &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], + IWLAGN_MIC_KEY_SIZE); + + data->use_tkip = true; + data->use_rsc_tsc = true; + break; + case WLAN_CIPHER_SUITE_CCMP: + if (sta) { + u8 *pn = seq.ccmp.pn; + + aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; + aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; + + ieee80211_get_key_tx_seq(key, &seq); + aes_tx_sc->pn = cpu_to_le64( + (u64)pn[5] | + ((u64)pn[4] << 8) | + ((u64)pn[3] << 16) | + ((u64)pn[2] << 24) | + ((u64)pn[1] << 32) | + ((u64)pn[0] << 40)); + } else + aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; + + /* + * For non-QoS this relies on the fact that both the uCode and + * mac80211 use TID 0 for checking the IV in the frames. + */ + for (i = 0; i < IWLAGN_NUM_RSC; i++) { + u8 *pn = seq.ccmp.pn; + + ieee80211_get_key_rx_seq(key, i, &seq); + aes_sc->pn = cpu_to_le64( + (u64)pn[5] | + ((u64)pn[4] << 8) | + ((u64)pn[3] << 16) | + ((u64)pn[2] << 24) | + ((u64)pn[1] << 32) | + ((u64)pn[0] << 40)); + } + data->use_rsc_tsc = true; + break; + } + + mutex_unlock(&priv->mutex); +} + +static int iwlagn_mac_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct iwl_priv *priv = hw->priv; + struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd; + struct iwl_rxon_cmd rxon; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; + struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; + struct wowlan_key_data key_data = { + .ctx = ctx, + .bssid = ctx->active.bssid_addr, + .use_rsc_tsc = false, + .tkip = &tkip_cmd, + .use_tkip = false, + }; + int ret, i; + u16 seq; + + if (WARN_ON(!wowlan)) + return -EINVAL; + + mutex_lock(&priv->mutex); + + /* Don't attempt WoWLAN when not associated, tear down instead. */ + if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || + !iwl_is_associated_ctx(ctx)) { + ret = 1; + goto out; + } + + key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); + if (!key_data.rsc_tsc) { + ret = -ENOMEM; + goto out; + } + + memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd)); + + /* + * We know the last used seqno, and the uCode expects to know that + * one, it will increment before TX. + */ + seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ; + wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq); + + /* + * For QoS counters, we store the one to use next, so subtract 0x10 + * since the uCode will add 0x10 before using the value. + */ + for (i = 0; i < 8; i++) { + seq = priv->stations[IWL_AP_ID].tid[i].seq_number; + seq -= 0x10; + wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); + } + + if (wowlan->disconnect) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS | + IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE); + if (wowlan->magic_pkt) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET); + if (wowlan->gtk_rekey_failure) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL); + if (wowlan->eap_identity_req) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ); + if (wowlan->four_way_handshake) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE); + if (wowlan->rfkill_release) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_RFKILL); + if (wowlan->n_patterns) + wakeup_filter_cmd.enabled |= + cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH); + + iwl_scan_cancel_timeout(priv, 200); + + memcpy(&rxon, &ctx->active, sizeof(rxon)); + + trans_stop_device(&priv->trans); + + priv->wowlan = true; + + ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan, + IWL_UCODE_WOWLAN); + if (ret) + goto error; + + /* now configure WoWLAN ucode */ + ret = iwl_alive_start(priv); + if (ret) + goto error; + + memcpy(&ctx->staging, &rxon, sizeof(rxon)); + ret = iwlagn_commit_rxon(priv, ctx); + if (ret) + goto error; + + ret = iwl_power_update_mode(priv, true); + if (ret) + goto error; + + if (!iwlagn_mod_params.sw_crypto) { + /* mark all keys clear */ + priv->ucode_key_table = 0; + ctx->key_mapping_keys = 0; + + /* + * This needs to be unlocked due to lock ordering + * constraints. Since we're in the suspend path + * that isn't really a problem though. + */ + mutex_unlock(&priv->mutex); + ieee80211_iter_keys(priv->hw, ctx->vif, + iwlagn_wowlan_program_keys, + &key_data); + mutex_lock(&priv->mutex); + if (key_data.error) { + ret = -EIO; + goto error; + } + + if (key_data.use_rsc_tsc) { + struct iwl_host_cmd rsc_tsc_cmd = { + .id = REPLY_WOWLAN_TSC_RSC_PARAMS, + .flags = CMD_SYNC, + .data[0] = key_data.rsc_tsc, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + .len[0] = sizeof(*key_data.rsc_tsc), + }; + + ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd); + if (ret) + goto error; + } + + if (key_data.use_tkip) { + ret = trans_send_cmd_pdu(&priv->trans, + REPLY_WOWLAN_TKIP_PARAMS, + CMD_SYNC, sizeof(tkip_cmd), + &tkip_cmd); + if (ret) + goto error; + } + + if (priv->have_rekey_data) { + memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd)); + memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN); + kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN); + memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN); + kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); + kek_kck_cmd.replay_ctr = priv->replay_ctr; + + ret = trans_send_cmd_pdu(&priv->trans, + REPLY_WOWLAN_KEK_KCK_MATERIAL, + CMD_SYNC, sizeof(kek_kck_cmd), + &kek_kck_cmd); + if (ret) + goto error; + } + } + + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER, + CMD_SYNC, sizeof(wakeup_filter_cmd), + &wakeup_filter_cmd); + if (ret) + goto error; + + ret = iwlagn_send_patterns(priv, wowlan); + if (ret) + goto error; + + device_set_wakeup_enable(priv->bus->dev, true); + + /* Now let the ucode operate on its own */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + + goto out; + + error: + priv->wowlan = false; + iwlagn_prepare_restart(priv); + ieee80211_restart_hw(priv->hw); + out: + mutex_unlock(&priv->mutex); + kfree(key_data.rsc_tsc); + return ret; +} + +static int iwlagn_mac_resume(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + struct ieee80211_vif *vif; + unsigned long flags; + u32 base, status = 0xffffffff; + int ret = -EIO; + + mutex_lock(&priv->mutex); + + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + + base = priv->device_pointers.error_event_table; + if (iwlagn_hw_valid_rtc_data_addr(base)) { + spin_lock_irqsave(&priv->reg_lock, flags); + ret = iwl_grab_nic_access_silent(priv); + if (ret == 0) { + iwl_write32(priv, HBUS_TARG_MEM_RADDR, base); + status = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, flags); + +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (ret == 0) { + if (!priv->wowlan_sram) + priv->wowlan_sram = + kzalloc(priv->ucode_wowlan.data.len, + GFP_KERNEL); + + if (priv->wowlan_sram) + _iwl_read_targ_mem_words( + priv, 0x800000, priv->wowlan_sram, + priv->ucode_wowlan.data.len / 4); + } +#endif + } + + /* we'll clear ctx->vif during iwlagn_prepare_restart() */ + vif = ctx->vif; + + priv->wowlan = false; + + device_set_wakeup_enable(priv->bus->dev, false); + + iwlagn_prepare_restart(priv); + + memset((void *)&ctx->active, 0, sizeof(ctx->active)); + iwl_connection_init_rx_config(priv, ctx); + iwlagn_set_rxon_chain(priv, ctx); + + mutex_unlock(&priv->mutex); + + ieee80211_resume_disconnect(vif); + + return 1; +} + static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; @@ -2678,14 +2762,8 @@ static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, u32 iv32, u16 *phase1key) { struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta, - iv32, phase1key); - IWL_DEBUG_MAC80211(priv, "leave\n"); + iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); } static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -2697,7 +2775,6 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_rxon_context *ctx = vif_priv->ctx; int ret; - u8 sta_id; bool is_default_wep_key = false; IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -2708,20 +2785,27 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } /* - * To support IBSS RSN, don't program group keys in IBSS, the - * hardware will then not attempt to decrypt the frames. + * We could program these keys into the hardware as well, but we + * don't expect much multicast traffic in IBSS and having keys + * for more stations is probably more useful. + * + * Mark key TX-only and return 0. */ if (vif->type == NL80211_IFTYPE_ADHOC && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) - return -EOPNOTSUPP; + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { + key->hw_key_idx = WEP_INVALID_OFFSET; + return 0; + } - sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); - if (sta_id == IWL_INVALID_STATION) - return -EINVAL; + /* If they key was TX-only, accept deletion */ + if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) + return 0; mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); + BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); + /* * If we are getting WEP group key and we didn't receive any key mapping * so far, we are in legacy wep mode (group key only), otherwise we are @@ -2729,22 +2813,30 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * In legacy wep mode, we use another host command to the uCode. */ if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || - key->cipher == WLAN_CIPHER_SUITE_WEP104) && - !sta) { + key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { if (cmd == SET_KEY) is_default_wep_key = !ctx->key_mapping_keys; else is_default_wep_key = - (key->hw_key_idx == HW_KEY_DEFAULT); + key->hw_key_idx == IWLAGN_HW_KEY_DEFAULT; } + switch (cmd) { case SET_KEY: - if (is_default_wep_key) + if (is_default_wep_key) { ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key); - else - ret = iwl_set_dynamic_key(priv, vif_priv->ctx, - key, sta_id); + break; + } + ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta); + if (ret) { + /* + * can't add key for RX, but we don't need it + * in the device for TX so still return 0 + */ + ret = 0; + key->hw_key_idx = WEP_INVALID_OFFSET; + } IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); break; @@ -2752,7 +2844,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (is_default_wep_key) ret = iwl_remove_default_wep_key(priv, ctx, key); else - ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id); + ret = iwl_remove_dynamic_key(priv, ctx, key, sta); IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); break; @@ -2799,18 +2891,18 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "start Tx\n"); ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); if (ret == 0) { - priv->_agn.agg_tids_count++; - IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", - priv->_agn.agg_tids_count); + priv->agg_tids_count++; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); } break; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); - if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { - priv->_agn.agg_tids_count--; - IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", - priv->_agn.agg_tids_count); + if ((ret == 0) && (priv->agg_tids_count > 0)) { + priv->agg_tids_count--; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ret = 0; @@ -2828,7 +2920,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size); + trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid, + buf_size); /* * If the limit is 0, then it wasn't initialised yet, @@ -2954,7 +3047,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, if (!iwl_is_associated_ctx(ctx)) goto out; - if (!priv->cfg->ops->lib->set_channel_switch) + if (!priv->cfg->lib->set_channel_switch) goto out; ch = channel->hw_value; @@ -3006,7 +3099,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, */ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = cpu_to_le16(ch); - if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) { + if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) { clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = 0; ieee80211_chswitch_done(ctx->vif, false); @@ -3116,7 +3209,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv) iwl_set_rxon_channel(priv, chan, ctx); iwl_set_flags_for_band(priv, ctx, chan->band, NULL); - priv->_agn.hw_roc_channel = NULL; + priv->hw_roc_channel = NULL; iwlagn_commit_rxon(priv, ctx); @@ -3126,7 +3219,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv) static void iwlagn_bg_roc_done(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, - _agn.hw_roc_work.work); + hw_roc_work.work); mutex_lock(&priv->mutex); ieee80211_remain_on_channel_expired(priv->hw); @@ -3158,11 +3251,11 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, } priv->contexts[IWL_RXON_CTX_PAN].is_active = true; - priv->_agn.hw_roc_channel = channel; - priv->_agn.hw_roc_chantype = channel_type; - priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); + priv->hw_roc_channel = channel; + priv->hw_roc_chantype = channel_type; + priv->hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); - queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work, + queue_delayed_work(priv->workqueue, &priv->hw_roc_work, msecs_to_jiffies(duration + 20)); msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */ @@ -3181,7 +3274,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) return -EOPNOTSUPP; - cancel_delayed_work_sync(&priv->_agn.hw_roc_work); + cancel_delayed_work_sync(&priv->hw_roc_work); mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); @@ -3203,18 +3296,17 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) init_waitqueue_head(&priv->wait_command_queue); INIT_WORK(&priv->restart, iwl_bg_restart); - INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); - INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); + INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done); iwl_setup_scan_deferred_work(priv); - if (priv->cfg->ops->lib->setup_deferred_work) - priv->cfg->ops->lib->setup_deferred_work(priv); + if (priv->cfg->lib->bt_setup_deferred_work) + priv->cfg->lib->bt_setup_deferred_work(priv); init_timer(&priv->statistics_periodic); priv->statistics_periodic.data = (unsigned long)priv; @@ -3227,15 +3319,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) init_timer(&priv->watchdog); priv->watchdog.data = (unsigned long)priv; priv->watchdog.function = iwl_bg_watchdog; - - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); } static void iwl_cancel_deferred_work(struct iwl_priv *priv) { - if (priv->cfg->ops->lib->cancel_deferred_work) - priv->cfg->ops->lib->cancel_deferred_work(priv); + if (priv->cfg->lib->cancel_deferred_work) + priv->cfg->lib->cancel_deferred_work(priv); cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); @@ -3286,7 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; - priv->_agn.agg_tids_count = 0; + priv->agg_tids_count = 0; /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = @@ -3340,6 +3429,9 @@ static void iwl_uninit_drv(struct iwl_priv *priv) iwl_free_channel_map(priv); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); +#ifdef CONFIG_IWLWIFI_DEBUGFS + kfree(priv->wowlan_sram); +#endif } static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, @@ -3369,6 +3461,8 @@ struct ieee80211_ops iwlagn_hw_ops = { .tx = iwlagn_mac_tx, .start = iwlagn_mac_start, .stop = iwlagn_mac_stop, + .suspend = iwlagn_mac_suspend, + .resume = iwlagn_mac_resume, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .change_interface = iwl_mac_change_interface, @@ -3376,6 +3470,7 @@ struct ieee80211_ops iwlagn_hw_ops = { .configure_filter = iwlagn_configure_filter, .set_key = iwlagn_mac_set_key, .update_tkip_key = iwlagn_mac_update_tkip_key, + .set_rekey_data = iwlagn_mac_set_rekey_data, .conf_tx = iwl_mac_conf_tx, .bss_info_changed = iwlagn_bss_info_changed, .ampdu_action = iwlagn_mac_ampdu_action, @@ -3415,7 +3510,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv) priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; /* Device-specific setup */ - return priv->cfg->ops->lib->set_hw_params(priv); + return priv->cfg->lib->set_hw_params(priv); } static const u8 iwlagn_bss_ac_to_fifo[] = { @@ -3521,8 +3616,7 @@ static void iwl_init_context(struct iwl_priv *priv) BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); } -int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, - struct iwl_cfg *cfg) +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) { int err = 0; struct iwl_priv *priv; @@ -3540,19 +3634,12 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, } priv = hw->priv; - - priv->bus.priv = priv; - priv->bus.bus_specific = bus_specific; - priv->bus.ops = bus_ops; - priv->bus.irq = priv->bus.ops->get_irq(&priv->bus); - priv->bus.ops->set_drv_data(&priv->bus, priv); - priv->bus.dev = priv->bus.ops->get_dev(&priv->bus); - - iwl_trans_register(&priv->trans); + priv->bus = bus; + bus_set_drv_data(priv->bus, priv); /* At this point both hw and priv are allocated. */ - SET_IEEE80211_DEV(hw, priv->bus.dev); + SET_IEEE80211_DEV(hw, priv->bus->dev); IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; @@ -3571,7 +3658,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, if (iwl_alloc_traffic_mem(priv)) IWL_ERR(priv, "Not enough memory to generate traffic log\n"); - /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ @@ -3592,10 +3678,14 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, hw_rev); - if (iwl_prepare_card_hw(priv)) { + err = iwl_trans_register(&priv->trans, priv); + if (err) + goto out_free_traffic_mem; + + if (trans_prepare_card_hw(&priv->trans)) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); - goto out_free_traffic_mem; + goto out_free_trans; } /***************** @@ -3605,7 +3695,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, err = iwl_eeprom_init(priv, hw_rev); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); - goto out_free_traffic_mem; + goto out_free_trans; } err = iwl_eeprom_check_version(priv); if (err) @@ -3652,15 +3742,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, /******************** * 7. Setup services ********************/ - iwl_alloc_isr_ict(priv); - - err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED, - DRV_NAME, priv); - if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq); - goto out_uninit_drv; - } - iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); iwl_testmode_init(priv); @@ -3683,7 +3764,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, iwl_power_initialize(priv); iwl_tt_initialize(priv); - init_completion(&priv->_agn.firmware_loading_complete); + init_completion(&priv->firmware_loading_complete); err = iwl_request_firmware(priv, true); if (err) @@ -3691,19 +3772,18 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, return 0; - out_destroy_workqueue: +out_destroy_workqueue: destroy_workqueue(priv->workqueue); priv->workqueue = NULL; - free_irq(priv->bus.irq, priv); - iwl_free_isr_ict(priv); - out_uninit_drv: iwl_uninit_drv(priv); - out_free_eeprom: +out_free_eeprom: iwl_eeprom_free(priv); - out_free_traffic_mem: +out_free_trans: + trans_free(&priv->trans); +out_free_traffic_mem: iwl_free_traffic_mem(priv); ieee80211_free_hw(priv->hw); - out: +out: return err; } @@ -3711,12 +3791,12 @@ void __devexit iwl_remove(struct iwl_priv * priv) { unsigned long flags; - wait_for_completion(&priv->_agn.firmware_loading_complete); + wait_for_completion(&priv->firmware_loading_complete); IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); iwl_dbgfs_unregister(priv); - sysfs_remove_group(&priv->bus.dev->kobj, + sysfs_remove_group(&priv->bus->dev->kobj, &iwl_attribute_group); /* ieee80211_unregister_hw call wil cause iwl_mac_stop to @@ -3745,16 +3825,15 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); + trans_sync_irq(&priv->trans); iwl_dealloc_ucode(priv); - trans_rx_free(priv); - trans_tx_free(priv); + trans_rx_free(&priv->trans); + trans_tx_free(&priv->trans); iwl_eeprom_free(priv); - /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); @@ -3765,12 +3844,11 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->workqueue = NULL; iwl_free_traffic_mem(priv); - free_irq(priv->bus.irq, priv); - priv->bus.ops->set_drv_data(&priv->bus, NULL); + trans_free(&priv->trans); - iwl_uninit_drv(priv); + bus_set_drv_data(priv->bus, NULL); - iwl_free_isr_ict(priv); + iwl_uninit_drv(priv); dev_kfree_skb(priv->beacon_skb); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5f58b44..d941c4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -113,18 +113,6 @@ extern struct iwl_mod_params iwlagn_mod_params; extern struct ieee80211_ops iwlagn_hw_ops; int iwl_reset_ict(struct iwl_priv *priv); -void iwl_disable_ict(struct iwl_priv *priv); -int iwl_alloc_isr_ict(struct iwl_priv *priv); -void iwl_free_isr_ict(struct iwl_priv *priv); -irqreturn_t iwl_isr_ict(int irq, void *data); - -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->bus.irq); - tasklet_kill(&priv->irq_tasklet); -} static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { @@ -134,22 +122,12 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) hdr->data_valid = 1; } -int iwl_prepare_card_hw(struct iwl_priv *priv); - -int iwlagn_start_device(struct iwl_priv *priv); -void iwlagn_stop_device(struct iwl_priv *priv); - /* tx queue */ -void iwlagn_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index); -void iwlagn_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry); -void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); /* RXON */ +int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed); @@ -171,32 +149,24 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, /* lib */ void iwl_check_abort_status(struct iwl_priv *priv, u8 frame_count, u32 status); -void iwlagn_rx_handler_setup(struct iwl_priv *priv); -void iwlagn_setup_deferred_work(struct iwl_priv *priv); int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_send_tx_power(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); -int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -int iwlagn_hw_nic_init(struct iwl_priv *priv); int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); +int iwlagn_send_beacon_cmd(struct iwl_priv *priv); /* rx */ -void iwlagn_rx_queue_restock(struct iwl_priv *priv); -void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); -void iwlagn_rx_replenish(struct iwl_priv *priv); -void iwlagn_rx_replenish_now(struct iwl_priv *priv); int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); void iwl_setup_rx_handlers(struct iwl_priv *priv); +void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); + /* tx */ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, int index); -int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, u8 reset); void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); @@ -204,13 +174,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); -void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, - struct ieee80211_sta *sta, - int tid, int frame_limit); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); static inline u32 iwl_tx_status_to_mac80211(u32 status) @@ -246,17 +214,6 @@ void iwlagn_post_scan(struct iwl_priv *priv); int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add); -/* hcmd */ -int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); -int iwlagn_send_beacon_cmd(struct iwl_priv *priv); -int iwlagn_set_pan_params(struct iwl_priv *priv); -void iwlagn_gain_computation(struct iwl_priv *priv, - u32 average_noise[NUM_RX_CHAINS], - u16 min_average_noise_antenna_i, - u32 min_average_noise, - u8 default_chain); - - /* bt coex */ void iwlagn_send_advance_bt_config(struct iwl_priv *priv); void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, @@ -289,11 +246,13 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, int iwl_restore_default_wep_keys(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *key, u8 sta_id); + struct ieee80211_key_conf *key, + struct ieee80211_sta *sta); int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *key, u8 sta_id); + struct ieee80211_key_conf *key, + struct ieee80211_sta *sta); void iwl_update_tkip_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, + struct ieee80211_vif *vif, struct ieee80211_key_conf *keyconf, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); @@ -379,8 +338,4 @@ void iwl_testmode_cleanup(struct iwl_priv *priv) } #endif -int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, - struct iwl_cfg *cfg); -void __devexit iwl_remove(struct iwl_priv * priv); - #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 9396c7c..f3ee1c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -63,6 +63,76 @@ #ifndef __iwl_pci_h__ #define __iwl_pci_h__ +struct iwl_bus; + +/** + * struct iwl_bus_ops - bus specific operations + * @get_pm_support: must returns true if the bus can go to sleep + * @apm_config: will be called during the config of the APM configuration + * @set_drv_data: set the drv_data pointer to the bus layer + * @get_hw_id: prints the hw_id in the provided buffer + * @write8: write a byte to register at offset ofs + * @write32: write a dword to register at offset ofs + * @wread32: read a dword at register at offset ofs + */ +struct iwl_bus_ops { + bool (*get_pm_support)(struct iwl_bus *bus); + void (*apm_config)(struct iwl_bus *bus); + void (*set_drv_data)(struct iwl_bus *bus, void *drv_data); + void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); + void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); + void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); + u32 (*read32)(struct iwl_bus *bus, u32 ofs); +}; + +struct iwl_bus { + /* Common data to all buses */ + void *drv_data; /* driver's context */ + struct device *dev; + struct iwl_bus_ops *ops; + + unsigned int irq; + + /* pointer to bus specific struct */ + /*Ensure that this pointer will always be aligned to sizeof pointer */ + char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); +}; + +static inline bool bus_get_pm_support(struct iwl_bus *bus) +{ + return bus->ops->get_pm_support(bus); +} + +static inline void bus_apm_config(struct iwl_bus *bus) +{ + bus->ops->apm_config(bus); +} + +static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data) +{ + bus->ops->set_drv_data(bus, drv_data); +} + +static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) +{ + bus->ops->get_hw_id(bus, buf, buf_len); +} + +static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val) +{ + bus->ops->write8(bus, ofs, val); +} + +static inline void bus_write32(struct iwl_bus *bus, u32 ofs, u32 val) +{ + bus->ops->write32(bus, ofs, val); +} + +static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) +{ + return bus->ops->read32(bus, ofs); +} + int __must_check iwl_pci_register_driver(void); void iwl_pci_unregister_driver(void); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index ee25637..5769ca5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -188,6 +188,13 @@ enum { REPLY_WIPAN_NOA_NOTIFICATION = 0xbc, REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd, + REPLY_WOWLAN_PATTERNS = 0xe0, + REPLY_WOWLAN_WAKEUP_FILTER = 0xe1, + REPLY_WOWLAN_TSC_RSC_PARAMS = 0xe2, + REPLY_WOWLAN_TKIP_PARAMS = 0xe3, + REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4, + REPLY_WOWLAN_GET_STATUS = 0xe5, + REPLY_MAX = 0xff }; @@ -832,6 +839,8 @@ struct iwl_qosparam_cmd { #define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) #define STA_KEY_MAX_NUM 8 #define STA_KEY_MAX_NUM_PAN 16 +/* must not match WEP_INVALID_OFFSET */ +#define IWLAGN_HW_KEY_DEFAULT 0xfe /* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 @@ -3155,7 +3164,6 @@ struct iwl_enhance_sensitivity_cmd { /* The default calibrate table size if not specified by firmware */ #define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18 enum { - IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, IWL_PHY_CALIBRATE_DC_CMD = 8, IWL_PHY_CALIBRATE_LO_CMD = 9, IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, @@ -3168,22 +3176,36 @@ enum { #define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253) -#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff) - /* This enum defines the bitmap of various calibrations to enable in both * init ucode and runtime ucode through CALIBRATION_CFG_CMD. */ enum iwl_ucode_calib_cfg { - IWL_CALIB_CFG_RX_BB_IDX, - IWL_CALIB_CFG_DC_IDX, - IWL_CALIB_CFG_TX_IQ_IDX, - IWL_CALIB_CFG_RX_IQ_IDX, - IWL_CALIB_CFG_NOISE_IDX, - IWL_CALIB_CFG_CRYSTAL_IDX, - IWL_CALIB_CFG_TEMPERATURE_IDX, - IWL_CALIB_CFG_PAPD_IDX, + IWL_CALIB_CFG_RX_BB_IDX = BIT(0), + IWL_CALIB_CFG_DC_IDX = BIT(1), + IWL_CALIB_CFG_LO_IDX = BIT(2), + IWL_CALIB_CFG_TX_IQ_IDX = BIT(3), + IWL_CALIB_CFG_RX_IQ_IDX = BIT(4), + IWL_CALIB_CFG_NOISE_IDX = BIT(5), + IWL_CALIB_CFG_CRYSTAL_IDX = BIT(6), + IWL_CALIB_CFG_TEMPERATURE_IDX = BIT(7), + IWL_CALIB_CFG_PAPD_IDX = BIT(8), + IWL_CALIB_CFG_SENSITIVITY_IDX = BIT(9), + IWL_CALIB_CFG_TX_PWR_IDX = BIT(10), }; +#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(IWL_CALIB_CFG_RX_BB_IDX | \ + IWL_CALIB_CFG_DC_IDX | \ + IWL_CALIB_CFG_LO_IDX | \ + IWL_CALIB_CFG_TX_IQ_IDX | \ + IWL_CALIB_CFG_RX_IQ_IDX | \ + IWL_CALIB_CFG_NOISE_IDX | \ + IWL_CALIB_CFG_CRYSTAL_IDX | \ + IWL_CALIB_CFG_TEMPERATURE_IDX | \ + IWL_CALIB_CFG_PAPD_IDX | \ + IWL_CALIB_CFG_SENSITIVITY_IDX | \ + IWL_CALIB_CFG_TX_PWR_IDX) + +#define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK cpu_to_le32(BIT(0)) struct iwl_calib_cfg_elmnt_s { __le32 is_enable; @@ -3217,15 +3239,6 @@ struct iwl_calib_cmd { u8 data[0]; } __packed; -/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */ -struct iwl_calib_diff_gain_cmd { - struct iwl_calib_hdr hdr; - s8 diff_gain_a; /* see above */ - s8 diff_gain_b; - s8 diff_gain_c; - u8 reserved1; -} __packed; - struct iwl_calib_xtal_freq_cmd { struct iwl_calib_hdr hdr; u8 cap_pin1; @@ -3233,11 +3246,11 @@ struct iwl_calib_xtal_freq_cmd { u8 pad[2]; } __packed; -#define DEFAULT_RADIO_SENSOR_OFFSET 2700 +#define DEFAULT_RADIO_SENSOR_OFFSET cpu_to_le16(2700) struct iwl_calib_temperature_offset_cmd { struct iwl_calib_hdr hdr; - s16 radio_sensor_offset; - s16 reserved; + __le16 radio_sensor_offset; + __le16 reserved; } __packed; /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ @@ -3758,6 +3771,127 @@ struct iwl_bt_coex_prot_env_cmd { u8 reserved[2]; } __attribute__((packed)); +/* + * REPLY_WOWLAN_PATTERNS + */ +#define IWLAGN_WOWLAN_MIN_PATTERN_LEN 16 +#define IWLAGN_WOWLAN_MAX_PATTERN_LEN 128 + +struct iwlagn_wowlan_pattern { + u8 mask[IWLAGN_WOWLAN_MAX_PATTERN_LEN / 8]; + u8 pattern[IWLAGN_WOWLAN_MAX_PATTERN_LEN]; + u8 mask_size; + u8 pattern_size; + __le16 reserved; +} __packed; + +#define IWLAGN_WOWLAN_MAX_PATTERNS 20 + +struct iwlagn_wowlan_patterns_cmd { + __le32 n_patterns; + struct iwlagn_wowlan_pattern patterns[]; +} __packed; + +/* + * REPLY_WOWLAN_WAKEUP_FILTER + */ +enum iwlagn_wowlan_wakeup_filters { + IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0), + IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1), + IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2), + IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3), + IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4), + IWLAGN_WOWLAN_WAKEUP_RFKILL = BIT(5), + IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR = BIT(6), + IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(7), + IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(8), + IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(9), + IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(10), +}; + +struct iwlagn_wowlan_wakeup_filter_cmd { + __le32 enabled; + __le16 non_qos_seq; + u8 min_sleep_seconds; + u8 reserved; + __le16 qos_seq[8]; +}; + +/* + * REPLY_WOWLAN_TSC_RSC_PARAMS + */ +#define IWLAGN_NUM_RSC 16 + +struct tkip_sc { + __le16 iv16; + __le16 pad; + __le32 iv32; +} __packed; + +struct iwlagn_tkip_rsc_tsc { + struct tkip_sc unicast_rsc[IWLAGN_NUM_RSC]; + struct tkip_sc multicast_rsc[IWLAGN_NUM_RSC]; + struct tkip_sc tsc; +} __packed; + +struct aes_sc { + __le64 pn; +} __packed; + +struct iwlagn_aes_rsc_tsc { + struct aes_sc unicast_rsc[IWLAGN_NUM_RSC]; + struct aes_sc multicast_rsc[IWLAGN_NUM_RSC]; + struct aes_sc tsc; +} __packed; + +union iwlagn_all_tsc_rsc { + struct iwlagn_tkip_rsc_tsc tkip; + struct iwlagn_aes_rsc_tsc aes; +}; + +struct iwlagn_wowlan_rsc_tsc_params_cmd { + union iwlagn_all_tsc_rsc all_tsc_rsc; +} __packed; + +/* + * REPLY_WOWLAN_TKIP_PARAMS + */ +#define IWLAGN_MIC_KEY_SIZE 8 +#define IWLAGN_P1K_SIZE 5 +struct iwlagn_mic_keys { + u8 tx[IWLAGN_MIC_KEY_SIZE]; + u8 rx_unicast[IWLAGN_MIC_KEY_SIZE]; + u8 rx_mcast[IWLAGN_MIC_KEY_SIZE]; +} __packed; + +struct iwlagn_p1k_cache { + __le16 p1k[IWLAGN_P1K_SIZE]; +} __packed; + +#define IWLAGN_NUM_RX_P1K_CACHE 2 + +struct iwlagn_wowlan_tkip_params_cmd { + struct iwlagn_mic_keys mic_keys; + struct iwlagn_p1k_cache tx; + struct iwlagn_p1k_cache rx_uni[IWLAGN_NUM_RX_P1K_CACHE]; + struct iwlagn_p1k_cache rx_multi[IWLAGN_NUM_RX_P1K_CACHE]; +} __packed; + +/* + * REPLY_WOWLAN_KEK_KCK_MATERIAL + */ + +#define IWLAGN_KCK_MAX_SIZE 32 +#define IWLAGN_KEK_MAX_SIZE 32 + +struct iwlagn_wowlan_kek_kck_material_cmd { + u8 kck[IWLAGN_KCK_MAX_SIZE]; + u8 kek[IWLAGN_KEK_MAX_SIZE]; + __le16 kck_len; + __le16 kek_len; + __le64 replay_ctr; +} __packed; + /****************************************************************************** * (13) * Union of all expected notifications/responses: diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index fa3d5ba..cf376f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -211,7 +211,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) { char buf[32]; - priv->bus.ops->get_hw_id(&priv->bus, buf, sizeof(buf)); + bus_get_hw_id(priv->bus, buf, sizeof(buf)); IWL_INFO(priv, "Incorrectly detected BG card as ABG. " "Please send your %s to maintainer.\n", buf); priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; @@ -363,6 +363,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } + ctx->beacon_int = beacon_int; + tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ interval_tm = beacon_int * TIME_UNIT; rem = do_div(tsf, interval_tm); @@ -376,7 +378,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return trans_send_cmd_pdu(priv, ctx->rxon_timing_cmd, + return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); } @@ -840,12 +842,12 @@ static void iwlagn_abort_notification_waits(struct iwl_priv *priv) unsigned long flags; struct iwl_notification_wait *wait_entry; - spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags); - list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list) + spin_lock_irqsave(&priv->notif_wait_lock, flags); + list_for_each_entry(wait_entry, &priv->notif_waits, list) wait_entry->aborted = true; - spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags); + spin_unlock_irqrestore(&priv->notif_wait_lock, flags); - wake_up_all(&priv->_agn.notif_waitq); + wake_up_all(&priv->notif_waitq); } void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) @@ -1012,7 +1014,7 @@ int iwl_apm_init(struct iwl_priv *priv) iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - priv->bus.ops->apm_config(&priv->bus); + bus_apm_config(priv->bus); /* Configure analog phase-lock-loop before activating to D0A */ if (priv->cfg->base_params->pll_cfg_val) @@ -1132,7 +1134,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - if (trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); } @@ -1145,12 +1147,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) }; if (flags & CMD_ASYNC) - return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_ASYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); else - return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_SYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); @@ -1903,8 +1905,12 @@ int iwl_suspend(struct iwl_priv *priv) * first but since iwl_mac_stop() has no knowledge of who the caller is, * it will not call apm_ops.stop() to stop the DMA operation. * Calling apm_ops.stop here to make sure we stop the DMA. + * + * But of course ... if we have configured WoWLAN then we did other + * things already :-) */ - iwl_apm_stop(priv); + if (!priv->wowlan) + iwl_apm_stop(priv); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 692c30c..3e6bb734 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -83,14 +83,12 @@ struct iwl_cmd; struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); - /* setup Rx handler */ - void (*rx_handler_setup)(struct iwl_priv *priv); - /* setup deferred work */ - void (*setup_deferred_work)(struct iwl_priv *priv); + /* setup BT Rx handler */ + void (*bt_rx_handler_setup)(struct iwl_priv *priv); + /* setup BT related deferred work */ + void (*bt_setup_deferred_work)(struct iwl_priv *priv); /* cancel deferred work */ void (*cancel_deferred_work)(struct iwl_priv *priv); - /* check validity of rtc data address */ - int (*is_valid_rtc_data_addr)(u32 addr); int (*set_channel_switch)(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch); /* device specific configuration */ @@ -103,16 +101,6 @@ struct iwl_lib_ops { void (*temperature)(struct iwl_priv *priv); }; -/* NIC specific ops */ -struct iwl_nic_ops { - void (*additional_nic_config)(struct iwl_priv *priv); -}; - -struct iwl_ops { - const struct iwl_lib_ops *lib; - const struct iwl_nic_ops *nic; -}; - struct iwl_mod_params { int sw_crypto; /* def: 0 = using hardware encryption */ int num_of_queues; /* def: HW dependent */ @@ -199,11 +187,22 @@ struct iwl_ht_params { /** * struct iwl_cfg + * @name: Offical name of the device * @fw_name_pre: Firmware filename prefix. The api version and extension * (.ucode) will be added to filename before loading from disk. The * filename is constructed as fw_name_pre<api>.ucode. * @ucode_api_max: Highest version of uCode API supported by driver. * @ucode_api_min: Lowest version of uCode API supported by driver. + * @valid_tx_ant: valid transmit antenna + * @valid_rx_ant: valid receive antenna + * @sku: sku information from EEPROM + * @eeprom_ver: EEPROM version + * @eeprom_calib_ver: EEPROM calibration version + * @lib: pointer to the lib ops + * @additional_nic_config: additional nic configuration + * @base_params: pointer to basic parameters + * @ht_params: point to ht patameters + * @bt_params: pointer to bt parameters * @pa_type: used by 6000 series only to identify the type of Power Amplifier * @need_dc_calib: need to perform init dc calibration * @need_temp_offset_calib: need to perform temperature offset calibration @@ -213,7 +212,6 @@ struct iwl_ht_params { * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device * @iq_invert: I/Q inversion - * @disable_otp_refresh: disable OTP refresh current limit * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -230,11 +228,7 @@ struct iwl_ht_params { * } * * The ideal usage of this infrastructure is to treat a new ucode API - * release as a new hardware revision. That is, through utilizing the - * iwl_hcmd_utils_ops etc. we accommodate different command structures - * and flows between hardware versions (4965/5000) as well as their API - * versions. - * + * release as a new hardware revision. */ struct iwl_cfg { /* params specific to an individual device within a device family */ @@ -247,7 +241,8 @@ struct iwl_cfg { u16 sku; u16 eeprom_ver; u16 eeprom_calib_ver; - const struct iwl_ops *ops; + const struct iwl_lib_ops *lib; + void (*additional_nic_config)(struct iwl_priv *priv); /* params not likely to change within a device family */ struct iwl_base_params *base_params; /* params likely to change within a device family */ @@ -262,7 +257,6 @@ struct iwl_cfg { const bool rx_with_siso_diversity; const bool internal_wimax_coex; const bool iq_invert; - const bool disable_otp_refresh; }; /*************************** @@ -340,21 +334,8 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, /***************************************************** * RX ******************************************************/ -void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl_rx_queue *q); -int iwl_rx_queue_space(const struct iwl_rx_queue *q); -void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); - void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); -/* TX helpers */ - -/***************************************************** -* TX -******************************************************/ -void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, - int count, int slots_num, u32 id); void iwl_setup_watchdog(struct iwl_priv *priv); /***************************************************** * TX power @@ -405,12 +386,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, *****************************************************/ const char *get_cmd_string(u8 cmd); -int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, - u16 len, const void *data); - -int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - void iwl_bg_watchdog(unsigned long data); u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, @@ -421,6 +396,9 @@ int iwl_suspend(struct iwl_priv *priv); int iwl_resume(struct iwl_priv *priv); #endif /* !CONFIG_PM */ +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); +void __devexit iwl_remove(struct iwl_priv * priv); + /***************************************************** * Error Handling Debugging ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 5ab90ba..d6dbb04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -351,6 +351,7 @@ #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) +#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE (0x00000020) /* GP Driver */ #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index eb95d1a..f9a407e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -32,10 +32,10 @@ struct iwl_priv; extern u32 iwl_debug_level; -#define IWL_ERR(p, f, a...) dev_err(p->bus.ops->get_dev(&p->bus), f, ## a) -#define IWL_WARN(p, f, a...) dev_warn(p->bus.ops->get_dev(&p->bus), f, ## a) -#define IWL_INFO(p, f, a...) dev_info(p->bus.ops->get_dev(&p->bus), f, ## a) -#define IWL_CRIT(p, f, a...) dev_crit(p->bus.ops->get_dev(&p->bus), f, ## a) +#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) +#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) +#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a) +#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a) #define iwl_print_hex_error(priv, p, len) \ do { \ @@ -78,8 +78,6 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); void iwl_dbgfs_unregister(struct iwl_priv *priv); -extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, - int bufsz); #else static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) { diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 6f9ebae..ec1485b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -322,6 +322,19 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + + if (!priv->wowlan_sram) + return -ENODATA; + + return simple_read_from_buffer(user_buf, count, ppos, + priv->wowlan_sram, + priv->ucode_wowlan.data.len); +} static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -856,6 +869,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, } DEBUGFS_READ_WRITE_FILE_OPS(sram); +DEBUGFS_READ_FILE_OPS(wowlan_sram); DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); @@ -1915,121 +1929,121 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), - priv->_agn.reply_tx_stats.pp_delay); + priv->reply_tx_stats.pp_delay); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), - priv->_agn.reply_tx_stats.pp_few_bytes); + priv->reply_tx_stats.pp_few_bytes); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), - priv->_agn.reply_tx_stats.pp_bt_prio); + priv->reply_tx_stats.pp_bt_prio); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), - priv->_agn.reply_tx_stats.pp_quiet_period); + priv->reply_tx_stats.pp_quiet_period); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), - priv->_agn.reply_tx_stats.pp_calc_ttak); + priv->reply_tx_stats.pp_calc_ttak); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_tx_fail_reason( TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), - priv->_agn.reply_tx_stats.int_crossed_retry); + priv->reply_tx_stats.int_crossed_retry); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), - priv->_agn.reply_tx_stats.short_limit); + priv->reply_tx_stats.short_limit); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), - priv->_agn.reply_tx_stats.long_limit); + priv->reply_tx_stats.long_limit); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), - priv->_agn.reply_tx_stats.fifo_underrun); + priv->reply_tx_stats.fifo_underrun); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), - priv->_agn.reply_tx_stats.drain_flow); + priv->reply_tx_stats.drain_flow); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), - priv->_agn.reply_tx_stats.rfkill_flush); + priv->reply_tx_stats.rfkill_flush); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), - priv->_agn.reply_tx_stats.life_expire); + priv->reply_tx_stats.life_expire); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), - priv->_agn.reply_tx_stats.dest_ps); + priv->reply_tx_stats.dest_ps); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), - priv->_agn.reply_tx_stats.host_abort); + priv->reply_tx_stats.host_abort); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), - priv->_agn.reply_tx_stats.pp_delay); + priv->reply_tx_stats.pp_delay); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), - priv->_agn.reply_tx_stats.sta_invalid); + priv->reply_tx_stats.sta_invalid); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), - priv->_agn.reply_tx_stats.frag_drop); + priv->reply_tx_stats.frag_drop); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), - priv->_agn.reply_tx_stats.tid_disable); + priv->reply_tx_stats.tid_disable); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), - priv->_agn.reply_tx_stats.fifo_flush); + priv->reply_tx_stats.fifo_flush); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_tx_fail_reason( TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), - priv->_agn.reply_tx_stats.insuff_cf_poll); + priv->reply_tx_stats.insuff_cf_poll); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), - priv->_agn.reply_tx_stats.fail_hw_drop); + priv->reply_tx_stats.fail_hw_drop); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_tx_fail_reason( TX_STATUS_FAIL_NO_BEACON_ON_RADAR), - priv->_agn.reply_tx_stats.sta_color_mismatch); + priv->reply_tx_stats.sta_color_mismatch); pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", - priv->_agn.reply_tx_stats.unknown); + priv->reply_tx_stats.unknown); pos += scnprintf(buf + pos, bufsz - pos, "\nStatistics_Agg_TX_Error:\n"); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), - priv->_agn.reply_agg_tx_stats.underrun); + priv->reply_agg_tx_stats.underrun); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), - priv->_agn.reply_agg_tx_stats.bt_prio); + priv->reply_agg_tx_stats.bt_prio); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), - priv->_agn.reply_agg_tx_stats.few_bytes); + priv->reply_agg_tx_stats.few_bytes); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), - priv->_agn.reply_agg_tx_stats.abort); + priv->reply_agg_tx_stats.abort); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_LAST_SENT_TTL_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_ttl); + priv->reply_agg_tx_stats.last_sent_ttl); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_try); + priv->reply_agg_tx_stats.last_sent_try); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), - priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); + priv->reply_agg_tx_stats.last_sent_bt_kill); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), - priv->_agn.reply_agg_tx_stats.scd_query); + priv->reply_agg_tx_stats.scd_query); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", iwl_get_agg_tx_fail_reason( AGG_TX_STATE_TEST_BAD_CRC32_MSK), - priv->_agn.reply_agg_tx_stats.bad_crc32); + priv->reply_agg_tx_stats.bad_crc32); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), - priv->_agn.reply_agg_tx_stats.response); + priv->reply_agg_tx_stats.response); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), - priv->_agn.reply_agg_tx_stats.dump_tx); + priv->reply_agg_tx_stats.dump_tx); pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), - priv->_agn.reply_agg_tx_stats.delay_tx); + priv->reply_agg_tx_stats.delay_tx); pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", - priv->_agn.reply_agg_tx_stats.unknown); + priv->reply_agg_tx_stats.unknown); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); @@ -2667,6 +2681,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 424c45c..6c9790c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -48,6 +48,8 @@ #include "iwl-power.h" #include "iwl-agn-rs.h" #include "iwl-agn-tt.h" +#include "iwl-bus.h" +#include "iwl-trans.h" #define DRV_NAME "iwlagn" @@ -396,13 +398,6 @@ struct iwl_tid_data { struct iwl_ht_agg agg; }; -struct iwl_hw_key { - u32 cipher; - int keylen; - u8 keyidx; - u8 key[32]; -}; - union iwl_ht_rate_supp { u16 rates; struct { @@ -455,7 +450,6 @@ struct iwl_station_entry { struct iwl_addsta_cmd sta; struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used, ctxid; - struct iwl_hw_key keyinfo; struct iwl_link_quality_cmd *lq; }; @@ -558,7 +552,8 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, - /* 16 and 17 reserved for future use */ + IWL_UCODE_TLV_WOWLAN_INST = 16, + IWL_UCODE_TLV_WOWLAN_DATA = 17, IWL_UCODE_TLV_FLAGS = 18, }; @@ -1158,6 +1153,8 @@ struct iwl_rxon_context { __le32 station_flags; + int beacon_int; + struct { bool non_gf_sta_present; u8 protection; @@ -1193,77 +1190,6 @@ struct iwl_testmode_trace { }; #endif -struct iwl_bus; - -/** - * struct iwl_bus_ops - bus specific operations - - * @get_pm_support: must returns true if the bus can go to sleep - * @apm_config: will be called during the config of the APM configuration - * @set_drv_data: set the priv pointer to the bus layer - * @get_dev: returns the device struct - * @get_irq: returns the irq number - * @get_hw_id: prints the hw_id in the provided buffer - * @write8: write a byte to register at offset ofs - * @write32: write a dword to register at offset ofs - * @wread32: read a dword at register at offset ofs - */ -struct iwl_bus_ops { - bool (*get_pm_support)(struct iwl_bus *bus); - void (*apm_config)(struct iwl_bus *bus); - void (*set_drv_data)(struct iwl_bus *bus, void *priv); - struct device *(*get_dev)(const struct iwl_bus *bus); - unsigned int (*get_irq)(const struct iwl_bus *bus); - void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); - void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); - void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); - u32 (*read32)(struct iwl_bus *bus, u32 ofs); -}; - -struct iwl_bus { - /* pointer to bus specific struct */ - void *bus_specific; - - /* Common data to all buses */ - struct iwl_priv *priv; /* driver's context */ - struct device *dev; - struct iwl_bus_ops *ops; - unsigned int irq; -}; - -struct iwl_trans; - -/** - * struct iwl_trans_ops - transport specific operations - - * @rx_init: inits the rx memory, allocate it if needed - * @rx_stop: stop the rx - * @rx_free: frees the rx memory - * @tx_init:inits the tx memory, allocate if needed - * @tx_stop: stop the tx - * @tx_free: frees the tx memory - * @send_cmd:send a host command - * @send_cmd_pdu:send a host command: flags can be CMD_* - */ -struct iwl_trans_ops { - int (*rx_init)(struct iwl_priv *priv); - int (*rx_stop)(struct iwl_priv *priv); - void (*rx_free)(struct iwl_priv *priv); - - int (*tx_init)(struct iwl_priv *priv); - int (*tx_stop)(struct iwl_priv *priv); - void (*tx_free)(struct iwl_priv *priv); - - int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - - int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, - const void *data); -}; - -struct iwl_trans { - const struct iwl_trans_ops *ops; -}; - /* uCode ownership */ #define IWL_OWNERSHIP_DRIVER 0 #define IWL_OWNERSHIP_TM 1 @@ -1335,7 +1261,7 @@ struct iwl_priv { spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; - struct iwl_bus bus; /* bus specific data */ + struct iwl_bus *bus; /* bus specific data */ struct iwl_trans trans; /* microcode/device supports multiple contexts */ @@ -1362,6 +1288,7 @@ struct iwl_priv { struct fw_img ucode_rt; struct fw_img ucode_init; + struct fw_img ucode_wowlan; enum iwlagn_ucode_type ucode_type; u8 ucode_write_complete; /* the image write is complete */ @@ -1434,6 +1361,8 @@ struct iwl_priv { u8 mac80211_registered; + bool wowlan; + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; @@ -1469,56 +1398,54 @@ struct iwl_priv { } accum_stats, delta_stats, max_delta_stats; #endif - struct { - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; - /* - * reporting the number of tids has AGG on. 0 means - * no AGGREGATION - */ - u8 agg_tids_count; - - struct iwl_rx_phy_res last_phy_res; - bool last_phy_res_valid; - - struct completion firmware_loading_complete; - - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; - - /* - * chain noise reset and gain commands are the - * two extra calibration commands follows the standard - * phy calibration commands - */ - u8 phy_calib_chain_noise_reset_cmd; - u8 phy_calib_chain_noise_gain_cmd; - - /* counts reply_tx error */ - struct reply_tx_error_statistics reply_tx_stats; - struct reply_agg_tx_error_statistics reply_agg_tx_stats; - /* notification wait support */ - struct list_head notif_waits; - spinlock_t notif_wait_lock; - wait_queue_head_t notif_waitq; - - /* remain-on-channel offload support */ - struct ieee80211_channel *hw_roc_channel; - struct delayed_work hw_roc_work; - enum nl80211_channel_type hw_roc_chantype; - int hw_roc_duration; - bool hw_roc_setup; - - struct sk_buff *offchan_tx_skb; - int offchan_tx_timeout; - struct ieee80211_channel *offchan_tx_chan; - } _agn; + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; + /* + * reporting the number of tids has AGG on. 0 means + * no AGGREGATION + */ + u8 agg_tids_count; + + struct iwl_rx_phy_res last_phy_res; + bool last_phy_res_valid; + + struct completion firmware_loading_complete; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; + + /* + * chain noise reset and gain commands are the + * two extra calibration commands follows the standard + * phy calibration commands + */ + u8 phy_calib_chain_noise_reset_cmd; + u8 phy_calib_chain_noise_gain_cmd; + + /* counts reply_tx error */ + struct reply_tx_error_statistics reply_tx_stats; + struct reply_agg_tx_error_statistics reply_agg_tx_stats; + /* notification wait support */ + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; + + /* remain-on-channel offload support */ + struct ieee80211_channel *hw_roc_channel; + struct delayed_work hw_roc_work; + enum nl80211_channel_type hw_roc_chantype; + int hw_roc_duration; + bool hw_roc_setup; + + struct sk_buff *offchan_tx_skb; + int offchan_tx_timeout; + struct ieee80211_channel *offchan_tx_chan; /* bt coex */ u8 bt_enable_flag; @@ -1588,6 +1515,7 @@ struct iwl_priv { struct dentry *debugfs_dir; u32 dbgfs_sram_offset, dbgfs_sram_len; bool disable_ht40; + void *wowlan_sram; #endif /* CONFIG_IWLWIFI_DEBUGFS */ struct work_struct txpower_work; @@ -1605,9 +1533,14 @@ struct iwl_priv { bool led_registered; #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL struct iwl_testmode_trace testmode_trace; -#endif u32 tm_fixed_rate; +#endif + /* WoWLAN GTK rekey data */ + u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; + __le64 replay_ctr; + __le16 last_seq_ctl; + bool have_rekey_data; }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index eee97bc..19d31a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -543,7 +543,7 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, const struct iwl_eeprom_channel **eeprom_ch_info, const u8 **eeprom_ch_index) { - u32 offset = priv->cfg->ops->lib-> + u32 offset = priv->cfg->lib-> eeprom_ops.regulatory_bands[eep_band - 1]; switch (eep_band) { case 1: /* 2.4GHz band */ @@ -749,9 +749,9 @@ int iwl_init_channel_map(struct iwl_priv *priv) } /* Check if we do have HT40 channels */ - if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] == + if (priv->cfg->lib->eeprom_ops.regulatory_bands[5] == EEPROM_REGULATORY_BAND_NO_HT40 && - priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] == + priv->cfg->lib->eeprom_ops.regulatory_bands[6] == EEPROM_REGULATORY_BAND_NO_HT40) return 0; @@ -787,8 +787,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) * driver need to process addition information * to determine the max channel tx power limits */ - if (priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower) - priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower(priv); + if (priv->cfg->lib->eeprom_ops.update_enhanced_txpower) + priv->cfg->lib->eeprom_ops.update_enhanced_txpower(priv); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c deleted file mode 100644 index 6cff8c1..0000000 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ /dev/null @@ -1,271 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless <ilw@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <net/mac80211.h> - -#include "iwl-dev.h" /* FIXME: remove */ -#include "iwl-debug.h" -#include "iwl-eeprom.h" -#include "iwl-core.h" - - -const char *get_cmd_string(u8 cmd) -{ - switch (cmd) { - IWL_CMD(REPLY_ALIVE); - IWL_CMD(REPLY_ERROR); - IWL_CMD(REPLY_RXON); - IWL_CMD(REPLY_RXON_ASSOC); - IWL_CMD(REPLY_QOS_PARAM); - IWL_CMD(REPLY_RXON_TIMING); - IWL_CMD(REPLY_ADD_STA); - IWL_CMD(REPLY_REMOVE_STA); - IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_TXFIFO_FLUSH); - IWL_CMD(REPLY_WEPKEY); - IWL_CMD(REPLY_TX); - IWL_CMD(REPLY_LEDS_CMD); - IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); - IWL_CMD(COEX_PRIORITY_TABLE_CMD); - IWL_CMD(COEX_MEDIUM_NOTIFICATION); - IWL_CMD(COEX_EVENT_CMD); - IWL_CMD(REPLY_QUIET_CMD); - IWL_CMD(REPLY_CHANNEL_SWITCH); - IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); - IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); - IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); - IWL_CMD(POWER_TABLE_CMD); - IWL_CMD(PM_SLEEP_NOTIFICATION); - IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); - IWL_CMD(REPLY_SCAN_CMD); - IWL_CMD(REPLY_SCAN_ABORT_CMD); - IWL_CMD(SCAN_START_NOTIFICATION); - IWL_CMD(SCAN_RESULTS_NOTIFICATION); - IWL_CMD(SCAN_COMPLETE_NOTIFICATION); - IWL_CMD(BEACON_NOTIFICATION); - IWL_CMD(REPLY_TX_BEACON); - IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); - IWL_CMD(QUIET_NOTIFICATION); - IWL_CMD(REPLY_TX_PWR_TABLE_CMD); - IWL_CMD(MEASURE_ABORT_NOTIFICATION); - IWL_CMD(REPLY_BT_CONFIG); - IWL_CMD(REPLY_STATISTICS_CMD); - IWL_CMD(STATISTICS_NOTIFICATION); - IWL_CMD(REPLY_CARD_STATE_CMD); - IWL_CMD(CARD_STATE_NOTIFICATION); - IWL_CMD(MISSED_BEACONS_NOTIFICATION); - IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); - IWL_CMD(SENSITIVITY_CMD); - IWL_CMD(REPLY_PHY_CALIBRATION_CMD); - IWL_CMD(REPLY_RX_PHY_CMD); - IWL_CMD(REPLY_RX_MPDU_CMD); - IWL_CMD(REPLY_RX); - IWL_CMD(REPLY_COMPRESSED_BA); - IWL_CMD(CALIBRATION_CFG_CMD); - IWL_CMD(CALIBRATION_RES_NOTIFICATION); - IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); - IWL_CMD(REPLY_TX_POWER_DBM_CMD); - IWL_CMD(TEMPERATURE_NOTIFICATION); - IWL_CMD(TX_ANT_CONFIGURATION_CMD); - IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); - IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); - IWL_CMD(REPLY_BT_COEX_PROT_ENV); - IWL_CMD(REPLY_WIPAN_PARAMS); - IWL_CMD(REPLY_WIPAN_RXON); - IWL_CMD(REPLY_WIPAN_RXON_TIMING); - IWL_CMD(REPLY_WIPAN_RXON_ASSOC); - IWL_CMD(REPLY_WIPAN_QOS_PARAM); - IWL_CMD(REPLY_WIPAN_WEPKEY); - IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); - IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); - IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); - default: - return "UNKNOWN"; - - } -} - -#define HOST_COMPLETE_TIMEOUT (2 * HZ) - -static void iwl_generic_cmd_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct iwl_rx_packet *pkt) -{ - if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - switch (cmd->hdr.cmd) { - case REPLY_TX_LINK_QUALITY_CMD: - case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); - break; - default: - IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); - } -#endif -} - -static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - int ret; - - /* An asynchronous command can not expect an SKB to be set. */ - if (WARN_ON(cmd->flags & CMD_WANT_SKB)) - return -EINVAL; - - /* Assign a generic callback if one is not provided */ - if (!cmd->callback) - cmd->callback = iwl_generic_cmd_callback; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return -EBUSY; - - ret = iwl_enqueue_hcmd(priv, cmd); - if (ret < 0) { - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - return ret; - } - return 0; -} - -static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - int cmd_idx; - int ret; - - lockdep_assert_held(&priv->mutex); - - /* A synchronous command can not have a callback set. */ - if (WARN_ON(cmd->callback)) - return -EINVAL; - - IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", - get_cmd_string(cmd->id)); - - set_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", - get_cmd_string(cmd->id)); - - cmd_idx = iwl_enqueue_hcmd(priv, cmd); - if (cmd_idx < 0) { - ret = cmd_idx; - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - return ret; - } - - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &priv->status), - HOST_COMPLETE_TIMEOUT); - if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { - IWL_ERR(priv, - "Error sending %s: time out after %dms.\n", - get_cmd_string(cmd->id), - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", - get_cmd_string(cmd->id)); - ret = -ETIMEDOUT; - goto cancel; - } - } - - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", - get_cmd_string(cmd->id)); - ret = -ECANCELED; - goto fail; - } - if (test_bit(STATUS_FW_ERROR, &priv->status)) { - IWL_ERR(priv, "Command %s failed: FW Error\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto fail; - } - if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { - IWL_ERR(priv, "Error: Response NULL in '%s'\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto cancel; - } - - return 0; - -cancel: - if (cmd->flags & CMD_WANT_SKB) { - /* - * Cancel the CMD_WANT_SKB flag for the cmd in the - * TX cmd queue. Otherwise in case the cmd comes - * in later, it will possibly set an invalid - * address (cmd->meta.source). - */ - priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= - ~CMD_WANT_SKB; - } -fail: - if (cmd->reply_page) { - iwl_free_pages(priv, cmd->reply_page); - cmd->reply_page = 0; - } - - return ret; -} - -int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - if (cmd->flags & CMD_ASYNC) - return iwl_send_cmd_async(priv, cmd); - - return iwl_send_cmd_sync(priv, cmd); -} - -int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, - const void *data) -{ - struct iwl_host_cmd cmd = { - .id = id, - .len = { len, }, - .data = { data, }, - .flags = flags, - }; - - return iwl_send_cmd(priv, &cmd); -} diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index c56eae7..19a0931 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -34,22 +34,23 @@ #include "iwl-dev.h" #include "iwl-debug.h" #include "iwl-devtrace.h" +#include "iwl-bus.h" static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) { trace_iwlwifi_dev_iowrite8(priv, ofs, val); - priv->bus.ops->write8(&priv->bus, ofs, val); + bus_write8(priv->bus, ofs, val); } static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) { trace_iwlwifi_dev_iowrite32(priv, ofs, val); - priv->bus.ops->write32(&priv->bus, ofs, val); + bus_write32(priv->bus, ofs, val); } static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) { - u32 val = priv->bus.ops->read32(&priv->bus, ofs); + u32 val = bus_read32(priv->bus, ofs); trace_iwlwifi_dev_ioread32(priv, ofs, val); return val; } diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 60e4169f..a67ae56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -112,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } /* Set led pattern command */ @@ -203,7 +203,7 @@ void iwl_leds_init(struct iwl_priv *priv) break; } - ret = led_classdev_register(priv->bus.dev, + ret = led_classdev_register(priv->bus->dev, &priv->led); if (ret) { kfree(priv->led.name); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 7491134..fb7e436 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -63,11 +63,10 @@ #include <linux/pci.h> #include <linux/pci-aspm.h> -#include "iwl-pci.h" +#include "iwl-bus.h" #include "iwl-agn.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-trans.h" /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -121,30 +120,20 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(bus->priv, CSR_GIO_REG, + iwl_set_bit(bus->drv_data, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - IWL_DEBUG_POWER(bus->priv, "L1 Enabled; Disabling L0S\n"); + dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(bus->priv, CSR_GIO_REG, + iwl_clear_bit(bus->drv_data, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - IWL_DEBUG_POWER(bus->priv, "L1 Disabled; Enabling L0S\n"); + dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); } } -static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_priv) +static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) { - pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_priv); -} - -static struct device *iwl_pci_get_dev(const struct iwl_bus *bus) -{ - return &(IWL_BUS_GET_PCI_DEV(bus)->dev); -} - -static unsigned int iwl_pci_get_irq(const struct iwl_bus *bus) -{ - return IWL_BUS_GET_PCI_DEV(bus)->irq; + bus->drv_data = drv_data; } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -176,8 +165,6 @@ static struct iwl_bus_ops pci_ops = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, .set_drv_data = iwl_pci_set_drv_data, - .get_dev = iwl_pci_get_dev, - .get_irq = iwl_pci_get_irq, .get_hw_id = iwl_pci_get_hw_id, .write8 = iwl_pci_write8, .write32 = iwl_pci_write32, @@ -383,18 +370,21 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - struct iwl_pci_bus *bus; + struct iwl_bus *bus; + struct iwl_pci_bus *pci_bus; u16 pci_cmd; int err; - bus = kzalloc(sizeof(*bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL); if (!bus) { - pr_err("Couldn't allocate iwl_pci_bus"); + dev_printk(KERN_ERR, &pdev->dev, + "Couldn't allocate iwl_pci_bus"); err = -ENOMEM; goto out_no_pci; } - bus->pci_dev = pdev; + pci_bus = IWL_BUS_GET_PCI_BUS(bus); + pci_bus->pci_dev = pdev; /* W/A - seems to solve weird behavior. We need to remove this if we * don't want to stay in L1 all the time. This wastes a lot of power */ @@ -418,29 +408,33 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) DMA_BIT_MASK(32)); /* both attempts failed: */ if (err) { - pr_err("No suitable DMA available.\n"); + dev_printk(KERN_ERR, bus->dev, + "No suitable DMA available.\n"); goto out_pci_disable_device; } } err = pci_request_regions(pdev, DRV_NAME); if (err) { - pr_err("pci_request_regions failed"); + dev_printk(KERN_ERR, bus->dev, "pci_request_regions failed"); goto out_pci_disable_device; } - bus->hw_base = pci_iomap(pdev, 0, 0); - if (!bus->hw_base) { - pr_err("pci_iomap failed"); + pci_bus->hw_base = pci_iomap(pdev, 0, 0); + if (!pci_bus->hw_base) { + dev_printk(KERN_ERR, bus->dev, "pci_iomap failed"); err = -ENODEV; goto out_pci_release_regions; } - pr_info("pci_resource_len = 0x%08llx\n", + dev_printk(KERN_INFO, &pdev->dev, + "pci_resource_len = 0x%08llx\n", (unsigned long long) pci_resource_len(pdev, 0)); - pr_info("pci_resource_base = %p\n", bus->hw_base); + dev_printk(KERN_INFO, &pdev->dev, + "pci_resource_base = %p\n", pci_bus->hw_base); - pr_info("HW Revision ID = 0x%X\n", pdev->revision); + dev_printk(KERN_INFO, &pdev->dev, + "HW Revision ID = 0x%X\n", pdev->revision); /* We disable the RETRY_TIMEOUT register (0x41) to keep * PCI Tx retries from interfering with C3 CPU state */ @@ -448,7 +442,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_enable_msi(pdev); if (err) { - pr_err("pci_enable_msi failed"); + dev_printk(KERN_ERR, &pdev->dev, "pci_enable_msi failed"); goto out_iounmap; } @@ -460,7 +454,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); } - err = iwl_probe((void *) bus, &pci_ops, cfg); + pci_set_drvdata(pdev, bus); + + bus->dev = &pdev->dev; + bus->irq = pdev->irq; + bus->ops = &pci_ops; + + err = iwl_probe(bus, cfg); if (err) goto out_disable_msi; return 0; @@ -468,7 +468,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_disable_msi: pci_disable_msi(pdev); out_iounmap: - pci_iounmap(pdev, bus->hw_base); + pci_iounmap(pdev, pci_bus->hw_base); out_pci_release_regions: pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); @@ -479,9 +479,9 @@ out_no_pci: return err; } -static void iwl_pci_down(void *bus) +static void iwl_pci_down(struct iwl_bus *bus) { - struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus; + struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific; pci_disable_msi(pci_bus->pci_dev); pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); @@ -489,17 +489,16 @@ static void iwl_pci_down(void *bus) pci_disable_device(pci_bus->pci_dev); pci_set_drvdata(pci_bus->pci_dev, NULL); - kfree(pci_bus); + kfree(bus); } static void __devexit iwl_pci_remove(struct pci_dev *pdev) { - struct iwl_priv *priv = pci_get_drvdata(pdev); - void *bus_specific = priv->bus.bus_specific; + struct iwl_bus *bus = pci_get_drvdata(pdev); - iwl_remove(priv); + iwl_remove(bus->drv_data); - iwl_pci_down(bus_specific); + iwl_pci_down(bus); } #ifdef CONFIG_PM @@ -507,15 +506,25 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = pci_get_drvdata(pdev); + + /* Before you put code here, think about WoWLAN. You cannot check here + * whether WoWLAN is enabled or not, and your code will run even if + * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. + */ - return iwl_suspend(priv); + return iwl_suspend(bus->drv_data); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = pci_get_drvdata(pdev); + + /* Before you put code here, think about WoWLAN. You cannot check here + * whether WoWLAN is enabled or not, and your code will run even if + * WoWLAN is enabled - the NIC may be alive. + */ /* * We disable the RETRY_TIMEOUT register (0x41) to keep @@ -523,7 +532,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_resume(priv); + return iwl_resume(bus->drv_data); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 64ff40a..3ec619c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -335,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return trans_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); } @@ -347,7 +347,9 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) + if (priv->wowlan) + iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); + else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (iwl_tt_is_low_power_state(priv)) { /* in thermal throttling low power state */ @@ -432,7 +434,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) /* initialize to default */ void iwl_power_initialize(struct iwl_priv *priv) { - priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus); + priv->power_data.bus_pm = bus_get_pm_support(priv->bus); priv->power_data.debug_sleep_level_override = -1; diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 1cc0ed1..2f267b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -178,61 +178,61 @@ #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 -#define IWL_SCD_TXFIFO_POS_TID (0) -#define IWL_SCD_TXFIFO_POS_RA (4) -#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) +#define SCD_TXFIFO_POS_TID (0) +#define SCD_TXFIFO_POS_RA (4) +#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) /* agn SCD */ -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF (0) -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL (4) -#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) -#define IWLAGN_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) - -#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) -#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) -#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) -#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) -#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) -#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) -#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) -#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) +#define SCD_QUEUE_STTS_REG_POS_TXF (0) +#define SCD_QUEUE_STTS_REG_POS_ACTIVE (3) +#define SCD_QUEUE_STTS_REG_POS_WSL (4) +#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) +#define SCD_QUEUE_STTS_REG_MSK (0x00FF0000) + +#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) +#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) +#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) +#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) +#define SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) +#define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) +#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) +#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) /* Context Data */ -#define IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) -#define IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) +#define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) +#define SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) /* Tx status */ -#define IWLAGN_SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) -#define IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) +#define SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) +#define SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) /* Translation Data */ -#define IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) -#define IWLAGN_SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808) +#define SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) +#define SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808) -#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ - (IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) +#define SCD_CONTEXT_QUEUE_OFFSET(x)\ + (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) -#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) +#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \ + ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) -#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \ +#define SCD_QUEUECHAIN_SEL_ALL(priv) \ (((1<<(priv)->hw_params.max_txq_num) - 1) &\ (~(1<<(priv)->cmd_queue))) -#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00) - -#define IWLAGN_SCD_SRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x0) -#define IWLAGN_SCD_DRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x8) -#define IWLAGN_SCD_AIT (IWLAGN_SCD_BASE + 0x0c) -#define IWLAGN_SCD_TXFACT (IWLAGN_SCD_BASE + 0x10) -#define IWLAGN_SCD_ACTIVE (IWLAGN_SCD_BASE + 0x14) -#define IWLAGN_SCD_QUEUE_WRPTR(x) (IWLAGN_SCD_BASE + 0x18 + (x) * 4) -#define IWLAGN_SCD_QUEUE_RDPTR(x) (IWLAGN_SCD_BASE + 0x68 + (x) * 4) -#define IWLAGN_SCD_QUEUECHAIN_SEL (IWLAGN_SCD_BASE + 0xe8) -#define IWLAGN_SCD_AGGR_SEL (IWLAGN_SCD_BASE + 0x248) -#define IWLAGN_SCD_INTERRUPT_MASK (IWLAGN_SCD_BASE + 0x108) -#define IWLAGN_SCD_QUEUE_STATUS_BITS(x) (IWLAGN_SCD_BASE + 0x10c + (x) * 4) +#define SCD_BASE (PRPH_BASE + 0xa02c00) + +#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0) +#define SCD_DRAM_BASE_ADDR (SCD_BASE + 0x8) +#define SCD_AIT (SCD_BASE + 0x0c) +#define SCD_TXFACT (SCD_BASE + 0x10) +#define SCD_ACTIVE (SCD_BASE + 0x14) +#define SCD_QUEUE_WRPTR(x) (SCD_BASE + 0x18 + (x) * 4) +#define SCD_QUEUE_RDPTR(x) (SCD_BASE + 0x68 + (x) * 4) +#define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) +#define SCD_AGGR_SEL (SCD_BASE + 0x248) +#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) +#define SCD_QUEUE_STATUS_BITS(x) (SCD_BASE + 0x10c + (x) * 4) /*********************** END TX SCHEDULER *************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f3f3efe..8e31400 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -41,142 +41,6 @@ #include "iwl-agn-calib.h" #include "iwl-agn.h" -/****************************************************************************** - * - * RX path functions - * - ******************************************************************************/ - -/* - * Rx theory of operation - * - * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs), - * each of which point to Receive Buffers to be filled by the NIC. These get - * used not only for Rx frames, but for any command response or notification - * from the NIC. The driver and NIC manage the Rx buffers by means - * of indexes into the circular buffer. - * - * Rx Queue Indexes - * The host/firmware share two index registers for managing the Rx buffers. - * - * The READ index maps to the first position that the firmware may be writing - * to -- the driver can read up to (but not including) this position and get - * good data. - * The READ index is managed by the firmware once the card is enabled. - * - * The WRITE index maps to the last position the driver has read from -- the - * position preceding WRITE is the last slot the firmware can place a packet. - * - * The queue is empty (no good data) if WRITE = READ - 1, and is full if - * WRITE = READ. - * - * During initialization, the host sets up the READ queue position to the first - * INDEX position, and WRITE to the last (READ - 1 wrapped) - * - * When the firmware places a packet in a buffer, it will advance the READ index - * and fire the RX interrupt. The driver can then query the READ index and - * process as many packets as possible, moving the WRITE index forward as it - * resets the Rx queue buffers with new memory. - * - * The management in the driver is as follows: - * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When - * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled - * to replenish the iwl->rxq->rx_free. - * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the - * iwl->rxq is replenished and the READ INDEX is updated (updating the - * 'processed' and 'read' driver indexes as well) - * + A received packet is processed and handed to the kernel network stack, - * detached from the iwl->rxq. The driver 'processed' index is updated. - * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free - * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ - * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there - * were enough free buffers and RX_STALLED is set it is cleared. - * - * - * Driver sequence: - * - * iwl_rx_queue_alloc() Allocates rx_free - * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls - * iwl_rx_queue_restock - * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx - * queue, updates firmware pointers, and updates - * the WRITE index. If insufficient rx_free buffers - * are available, schedules iwl_rx_replenish - * - * -- enable interrupts -- - * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the - * READ INDEX, detaching the SKB from the pool. - * Moves the packet buffer from queue to rx_used. - * Calls iwl_rx_queue_restock to refill any empty - * slots. - * ... - * - */ - -/** - * iwl_rx_queue_space - Return number of free slots available in queue. - */ -int iwl_rx_queue_space(const struct iwl_rx_queue *q) -{ - int s = q->read - q->write; - if (s <= 0) - s += RX_QUEUE_SIZE; - /* keep some buffer to not confuse full and empty queue */ - s -= 2; - if (s < 0) - s = 0; - return s; -} - -/** - * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue - */ -void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) -{ - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&q->lock, flags); - - if (q->need_update == 0) - goto exit_unlock; - - if (priv->cfg->base_params->shadow_reg_enable) { - /* shadow register enabled */ - /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); - iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); - } else { - /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, - "Rx queue requesting wakeup," - " GP1 = 0x%x\n", reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - goto exit_unlock; - } - - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, - q->write_actual); - - /* Else device is assumed to be awake */ - } else { - /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, - q->write_actual); - } - } - q->need_update = 0; - - exit_unlock: - spin_unlock_irqrestore(&q->lock, flags); -} /****************************************************************************** * @@ -306,7 +170,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, int actual_delta, expected_delta, ba_timeout_delta; struct statistics_tx *old; - if (priv->_agn.agg_tids_count) + if (priv->agg_tids_count) return true; old = &priv->statistics.tx; @@ -624,8 +488,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv, iwl_rx_calc_noise(priv); queue_work(priv->workqueue, &priv->run_time_calib_work); } - if (priv->cfg->ops->lib->temperature && change) - priv->cfg->ops->lib->temperature(priv); + if (priv->cfg->lib->temperature && change) + priv->cfg->lib->temperature(priv); } static void iwl_rx_reply_statistics(struct iwl_priv *priv, @@ -728,8 +592,8 @@ static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); - priv->_agn.last_phy_res_valid = true; - memcpy(&priv->_agn.last_phy_res, pkt->u.raw, + priv->last_phy_res_valid = true; + memcpy(&priv->last_phy_res, pkt->u.raw, sizeof(struct iwl_rx_phy_res)); } @@ -977,11 +841,11 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, phy_res->cfg_phy_cnt + len); ampdu_status = le32_to_cpu(rx_pkt_status); } else { - if (!priv->_agn.last_phy_res_valid) { + if (!priv->last_phy_res_valid) { IWL_ERR(priv, "MPDU frame without cached PHY data\n"); return; } - phy_res = &priv->_agn.last_phy_res; + phy_res = &priv->last_phy_res; amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); len = le16_to_cpu(amsdu->byte_count); @@ -1102,6 +966,64 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) /* block ack */ handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; - /* Set up hardware specific Rx handlers */ - priv->cfg->ops->lib->rx_handler_setup(priv); + /* init calibration handlers */ + priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = + iwlagn_rx_calib_result; + priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; + + /* set up notification wait support */ + spin_lock_init(&priv->notif_wait_lock); + INIT_LIST_HEAD(&priv->notif_waits); + init_waitqueue_head(&priv->notif_waitq); + + /* Set up BT Rx handlers */ + if (priv->cfg->lib->bt_rx_handler_setup) + priv->cfg->lib->bt_rx_handler_setup(priv); + +} + +void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + + /* + * Do the notification wait before RX handlers so + * even if the RX handler consumes the RXB we have + * access to it in the notification wait entry. + */ + if (!list_empty(&priv->notif_waits)) { + struct iwl_notification_wait *w; + + spin_lock(&priv->notif_wait_lock); + list_for_each_entry(w, &priv->notif_waits, list) { + if (w->cmd != pkt->hdr.cmd) + continue; + IWL_DEBUG_RX(priv, + "Notif: %s, 0x%02x - wake the callers up\n", + get_cmd_string(pkt->hdr.cmd), + pkt->hdr.cmd); + w->triggered = true; + if (w->fn) + w->fn(priv, pkt, w->fn_data); + } + spin_unlock(&priv->notif_wait_lock); + + wake_up_all(&priv->notif_waitq); + } + + if (priv->pre_rx_handler) + priv->pre_rx_handler(priv, rxb); + + /* Based on type of command response or notification, + * handle those that need handling via function in + * rx_handlers table. See iwl_setup_rx_handlers() */ + if (priv->rx_handlers[pkt->hdr.cmd]) { + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; + priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); + } else { + /* No handling needed */ + IWL_DEBUG_RX(priv, + "No handler needed for %s, 0x%02x\n", + get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + } } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index f6ebe29..dd6937e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -75,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EIO; - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -565,10 +565,10 @@ static void iwl_bg_scan_completed(struct work_struct *work) goto out_settings; } - if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) { + if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) { ieee80211_tx_status_irqsafe(priv->hw, - priv->_agn.offchan_tx_skb); - priv->_agn.offchan_tx_skb = NULL; + priv->offchan_tx_skb); + priv->offchan_tx_skb = NULL; } if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 65386e5..1ef3b71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -168,7 +168,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, } cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret || (flags & CMD_ASYNC)) return ret; @@ -424,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, cmd.flags |= CMD_WANT_SKB; - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -669,7 +669,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); } -int iwl_get_free_ucode_key_index(struct iwl_priv *priv) +int iwl_get_free_ucode_key_offset(struct iwl_priv *priv) { int i; @@ -793,7 +793,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) - ret = trans_send_cmd(priv, &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); else ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index ff64027..9a6768d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -31,9 +31,6 @@ #include "iwl-dev.h" -#define HW_KEY_DYNAMIC 0 -#define HW_KEY_DEFAULT 1 - #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of @@ -47,7 +44,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwl_clear_ucode_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwl_dealloc_bcast_stations(struct iwl_priv *priv); -int iwl_get_free_ucode_key_index(struct iwl_priv *priv); +int iwl_get_free_ucode_key_offset(struct iwl_priv *priv); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 77ed1c2..b11f60d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -181,12 +181,10 @@ void iwl_testmode_init(struct iwl_priv *priv) static void iwl_trace_cleanup(struct iwl_priv *priv) { - struct device *dev = priv->bus.dev; - if (priv->testmode_trace.trace_enabled) { if (priv->testmode_trace.cpu_addr && priv->testmode_trace.dma_addr) - dma_free_coherent(dev, + dma_free_coherent(priv->bus->dev, priv->testmode_trace.total_size, priv->testmode_trace.cpu_addr, priv->testmode_trace.dma_addr); @@ -241,7 +239,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ - return trans_send_cmd(priv, &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -407,7 +405,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: iwl_testmode_cfg_init_calib(priv); - iwlagn_stop_device(priv); + trans_stop_device(&priv->trans); break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: @@ -486,7 +484,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) struct iwl_priv *priv = hw->priv; struct sk_buff *skb; int status = 0; - struct device *dev = priv->bus.dev; + struct device *dev = priv->bus->dev; switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h new file mode 100644 index 0000000..b79330d --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ +#ifndef __iwl_trans_int_pcie_h__ +#define __iwl_trans_int_pcie_h__ + +/*This file includes the declaration that are internal to the + * trans_pcie layer */ + +/***************************************************** +* RX +******************************************************/ +void iwl_bg_rx_replenish(struct work_struct *data); +void iwl_irq_tasklet(struct iwl_priv *priv); +void iwlagn_rx_replenish(struct iwl_priv *priv); +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, + struct iwl_rx_queue *q); + +/***************************************************** +* ICT +******************************************************/ +int iwl_reset_ict(struct iwl_priv *priv); +void iwl_disable_ict(struct iwl_priv *priv); +int iwl_alloc_isr_ict(struct iwl_priv *priv); +void iwl_free_isr_ict(struct iwl_priv *priv); +irqreturn_t iwl_isr_ict(int irq, void *data); + + +/***************************************************** +* TX / HCMD +******************************************************/ +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int index); +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, u8 reset); +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, + int count, int slots_num, u32 id); +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, + u16 len, const void *data); +void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt); +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index); +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + int tx_fifo_id, int scd_retry); +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); + +#endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c new file mode 100644 index 0000000..4748602 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -0,0 +1,979 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ +#include <linux/sched.h> +#include <linux/wait.h> +#include <linux/gfp.h> + +#include "iwl-dev.h" +#include "iwl-agn.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-helpers.h" +#include "iwl-trans-int-pcie.h" + +/****************************************************************************** + * + * RX path functions + * + ******************************************************************************/ + +/* + * Rx theory of operation + * + * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs), + * each of which point to Receive Buffers to be filled by the NIC. These get + * used not only for Rx frames, but for any command response or notification + * from the NIC. The driver and NIC manage the Rx buffers by means + * of indexes into the circular buffer. + * + * Rx Queue Indexes + * The host/firmware share two index registers for managing the Rx buffers. + * + * The READ index maps to the first position that the firmware may be writing + * to -- the driver can read up to (but not including) this position and get + * good data. + * The READ index is managed by the firmware once the card is enabled. + * + * The WRITE index maps to the last position the driver has read from -- the + * position preceding WRITE is the last slot the firmware can place a packet. + * + * The queue is empty (no good data) if WRITE = READ - 1, and is full if + * WRITE = READ. + * + * During initialization, the host sets up the READ queue position to the first + * INDEX position, and WRITE to the last (READ - 1 wrapped) + * + * When the firmware places a packet in a buffer, it will advance the READ index + * and fire the RX interrupt. The driver can then query the READ index and + * process as many packets as possible, moving the WRITE index forward as it + * resets the Rx queue buffers with new memory. + * + * The management in the driver is as follows: + * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When + * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled + * to replenish the iwl->rxq->rx_free. + * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the + * iwl->rxq is replenished and the READ INDEX is updated (updating the + * 'processed' and 'read' driver indexes as well) + * + A received packet is processed and handed to the kernel network stack, + * detached from the iwl->rxq. The driver 'processed' index is updated. + * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free + * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ + * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there + * were enough free buffers and RX_STALLED is set it is cleared. + * + * + * Driver sequence: + * + * iwl_rx_queue_alloc() Allocates rx_free + * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls + * iwl_rx_queue_restock + * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx + * queue, updates firmware pointers, and updates + * the WRITE index. If insufficient rx_free buffers + * are available, schedules iwl_rx_replenish + * + * -- enable interrupts -- + * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the + * READ INDEX, detaching the SKB from the pool. + * Moves the packet buffer from queue to rx_used. + * Calls iwl_rx_queue_restock to refill any empty + * slots. + * ... + * + */ + +/** + * iwl_rx_queue_space - Return number of free slots available in queue. + */ +static int iwl_rx_queue_space(const struct iwl_rx_queue *q) +{ + int s = q->read - q->write; + if (s <= 0) + s += RX_QUEUE_SIZE; + /* keep some buffer to not confuse full and empty queue */ + s -= 2; + if (s < 0) + s = 0; + return s; +} + +/** + * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue + */ +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, + struct iwl_rx_queue *q) +{ + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&q->lock, flags); + + if (q->need_update == 0) + goto exit_unlock; + + if (priv->cfg->base_params->shadow_reg_enable) { + /* shadow register enabled */ + /* Device expects a multiple of 8 */ + q->write_actual = (q->write & ~0x7); + iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); + } else { + /* If power-saving is in use, make sure device is awake */ + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); + + if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { + IWL_DEBUG_INFO(priv, + "Rx queue requesting wakeup," + " GP1 = 0x%x\n", reg); + iwl_set_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + goto exit_unlock; + } + + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, + q->write_actual); + + /* Else device is assumed to be awake */ + } else { + /* Device expects a multiple of 8 */ + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, + q->write_actual); + } + } + q->need_update = 0; + + exit_unlock: + spin_unlock_irqrestore(&q->lock, flags); +} + +/** + * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr + */ +static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, + dma_addr_t dma_addr) +{ + return cpu_to_le32((u32)(dma_addr >> 8)); +} + +/** + * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool + * + * If there are slots in the RX queue that need to be restocked, + * and we have free pre-allocated buffers, fill the ranks as much + * as we can, pulling from rx_free. + * + * This moves the 'write' index forward to catch up with 'processed', and + * also updates the memory address in the firmware to reference the new + * target buffer. + */ +static void iwlagn_rx_queue_restock(struct iwl_priv *priv) +{ + struct iwl_rx_queue *rxq = &priv->rxq; + struct list_head *element; + struct iwl_rx_mem_buffer *rxb; + unsigned long flags; + + spin_lock_irqsave(&rxq->lock, flags); + while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { + /* The overwritten rxb must be a used one */ + rxb = rxq->queue[rxq->write]; + BUG_ON(rxb && rxb->page); + + /* Get next free Rx buffer, remove from free list */ + element = rxq->rx_free.next; + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + + /* Point to Rx buffer via next RBD in circular buffer */ + rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, + rxb->page_dma); + rxq->queue[rxq->write] = rxb; + rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; + rxq->free_count--; + } + spin_unlock_irqrestore(&rxq->lock, flags); + /* If the pre-allocated buffer pool is dropping low, schedule to + * refill it */ + if (rxq->free_count <= RX_LOW_WATERMARK) + queue_work(priv->workqueue, &priv->rx_replenish); + + + /* If we've added more space for the firmware to place data, tell it. + * Increment device's write pointer in multiples of 8. */ + if (rxq->write_actual != (rxq->write & ~0x7)) { + spin_lock_irqsave(&rxq->lock, flags); + rxq->need_update = 1; + spin_unlock_irqrestore(&rxq->lock, flags); + iwl_rx_queue_update_write_ptr(priv, rxq); + } +} + +/** + * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free + * + * When moving to rx_free an SKB is allocated for the slot. + * + * Also restock the Rx queue via iwl_rx_queue_restock. + * This is called as a scheduled work item (except for during initialization) + */ +static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) +{ + struct iwl_rx_queue *rxq = &priv->rxq; + struct list_head *element; + struct iwl_rx_mem_buffer *rxb; + struct page *page; + unsigned long flags; + gfp_t gfp_mask = priority; + + while (1) { + spin_lock_irqsave(&rxq->lock, flags); + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + return; + } + spin_unlock_irqrestore(&rxq->lock, flags); + + if (rxq->free_count > RX_LOW_WATERMARK) + gfp_mask |= __GFP_NOWARN; + + if (priv->hw_params.rx_page_order > 0) + gfp_mask |= __GFP_COMP; + + /* Alloc a new receive buffer */ + page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); + if (!page) { + if (net_ratelimit()) + IWL_DEBUG_INFO(priv, "alloc_pages failed, " + "order: %d\n", + priv->hw_params.rx_page_order); + + if ((rxq->free_count <= RX_LOW_WATERMARK) && + net_ratelimit()) + IWL_CRIT(priv, "Failed to alloc_pages with %s." + "Only %u free buffers remaining.\n", + priority == GFP_ATOMIC ? + "GFP_ATOMIC" : "GFP_KERNEL", + rxq->free_count); + /* We don't reschedule replenish work here -- we will + * call the restock method and if it still needs + * more buffers it will schedule replenish */ + return; + } + + spin_lock_irqsave(&rxq->lock, flags); + + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + __free_pages(page, priv->hw_params.rx_page_order); + return; + } + element = rxq->rx_used.next; + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + + spin_unlock_irqrestore(&rxq->lock, flags); + + BUG_ON(rxb->page); + rxb->page = page; + /* Get physical address of the RB */ + rxb->page_dma = dma_map_page(priv->bus->dev, page, 0, + PAGE_SIZE << priv->hw_params.rx_page_order, + DMA_FROM_DEVICE); + /* dma address must be no more than 36 bits */ + BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); + /* and also 256 byte aligned! */ + BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); + + spin_lock_irqsave(&rxq->lock, flags); + + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + + spin_unlock_irqrestore(&rxq->lock, flags); + } +} + +void iwlagn_rx_replenish(struct iwl_priv *priv) +{ + unsigned long flags; + + iwlagn_rx_allocate(priv, GFP_KERNEL); + + spin_lock_irqsave(&priv->lock, flags); + iwlagn_rx_queue_restock(priv); + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void iwlagn_rx_replenish_now(struct iwl_priv *priv) +{ + iwlagn_rx_allocate(priv, GFP_ATOMIC); + + iwlagn_rx_queue_restock(priv); +} + +void iwl_bg_rx_replenish(struct work_struct *data) +{ + struct iwl_priv *priv = + container_of(data, struct iwl_priv, rx_replenish); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + iwlagn_rx_replenish(priv); + mutex_unlock(&priv->mutex); +} + +/** + * iwl_rx_handle - Main entry function for receiving responses from uCode + * + * Uses the priv->rx_handlers callback function array to invoke + * the appropriate handlers, including command responses, + * frame-received notifications, and other notifications. + */ +static void iwl_rx_handle(struct iwl_priv *priv) +{ + struct iwl_rx_mem_buffer *rxb; + struct iwl_rx_packet *pkt; + struct iwl_rx_queue *rxq = &priv->rxq; + u32 r, i; + int reclaim; + unsigned long flags; + u8 fill_rx = 0; + u32 count = 8; + int total_empty; + + /* uCode's read index (stored in shared DRAM) indicates the last Rx + * buffer that the driver may process (last buffer filled by ucode). */ + r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; + i = rxq->read; + + /* Rx interrupt, but nothing sent from uCode */ + if (i == r) + IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); + + /* calculate total frames need to be restock after handling RX */ + total_empty = r - rxq->write_actual; + if (total_empty < 0) + total_empty += RX_QUEUE_SIZE; + + if (total_empty > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; + + while (i != r) { + int len; + + rxb = rxq->queue[i]; + + /* If an RXB doesn't have a Rx queue slot associated with it, + * then a bug has been introduced in the queue refilling + * routines -- catch it here */ + if (WARN_ON(rxb == NULL)) { + i = (i + 1) & RX_QUEUE_MASK; + continue; + } + + rxq->queue[i] = NULL; + + dma_unmap_page(priv->bus->dev, rxb->page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, + DMA_FROM_DEVICE); + pkt = rxb_addr(rxb); + + IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, + i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + + len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + len += sizeof(u32); /* account for status word */ + trace_iwlwifi_dev_rx(priv, pkt, len); + + /* Reclaim a command buffer only if this packet is a response + * to a (driver-originated) command. + * If the packet (e.g. Rx frame) originated from uCode, + * there is no command buffer to reclaim. + * Ucode should set SEQ_RX_FRAME bit if ucode-originated, + * but apparently a few don't get set; catch them here. */ + reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && + (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && + (pkt->hdr.cmd != REPLY_RX) && + (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && + (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && + (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && + (pkt->hdr.cmd != REPLY_TX); + + iwl_rx_dispatch(priv, rxb); + + /* + * XXX: After here, we should always check rxb->page + * against NULL before touching it or its virtual + * memory (pkt). Because some rx_handler might have + * already taken or freed the pages. + */ + + if (reclaim) { + /* Invoke any callbacks, transfer the buffer to caller, + * and fire off the (possibly) blocking + * trans_send_cmd() + * as we reclaim the driver command queue */ + if (rxb->page) + iwl_tx_cmd_complete(priv, rxb); + else + IWL_WARN(priv, "Claim null rxb?\n"); + } + + /* Reuse the page if possible. For notification packets and + * SKBs that fail to Rx correctly, add them back into the + * rx_free list for reuse later. */ + spin_lock_irqsave(&rxq->lock, flags); + if (rxb->page != NULL) { + rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page, + 0, PAGE_SIZE << priv->hw_params.rx_page_order, + DMA_FROM_DEVICE); + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + } else + list_add_tail(&rxb->list, &rxq->rx_used); + + spin_unlock_irqrestore(&rxq->lock, flags); + + i = (i + 1) & RX_QUEUE_MASK; + /* If there are a lot of unused frames, + * restock the Rx queue so ucode wont assert. */ + if (fill_rx) { + count++; + if (count >= 8) { + rxq->read = i; + iwlagn_rx_replenish_now(priv); + count = 0; + } + } + } + + /* Backtrack one entry */ + rxq->read = i; + if (fill_rx) + iwlagn_rx_replenish_now(priv); + else + iwlagn_rx_queue_restock(priv); +} + +/* tasklet for iwlagn interrupt */ +void iwl_irq_tasklet(struct iwl_priv *priv) +{ + u32 inta = 0; + u32 handled = 0; + unsigned long flags; + u32 i; +#ifdef CONFIG_IWLWIFI_DEBUG + u32 inta_mask; +#endif + + spin_lock_irqsave(&priv->lock, flags); + + /* Ack/clear/reset pending uCode interrupts. + * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, + */ + /* There is a hardware bug in the interrupt mask function that some + * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if + * they are disabled in the CSR_INT_MASK register. Furthermore the + * ICT interrupt handling mechanism has another bug that might cause + * these unmasked interrupts fail to be detected. We workaround the + * hardware bugs here by ACKing all the possible interrupts so that + * interrupt coalescing can still be achieved. + */ + iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); + + inta = priv->inta; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & IWL_DL_ISR) { + /* just for debug */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); + IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", + inta, inta_mask); + } +#endif + + spin_unlock_irqrestore(&priv->lock, flags); + + /* saved interrupt in inta variable now we can reset priv->inta */ + priv->inta = 0; + + /* Now service all interrupt bits discovered above. */ + if (inta & CSR_INT_BIT_HW_ERR) { + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); + + /* Tell the device to stop sending interrupts */ + iwl_disable_interrupts(priv); + + priv->isr_stats.hw++; + iwl_irq_handle_error(priv); + + handled |= CSR_INT_BIT_HW_ERR; + + return; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + /* NIC fires this, but we don't use it, redundant with WAKEUP */ + if (inta & CSR_INT_BIT_SCD) { + IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " + "the frame/frames.\n"); + priv->isr_stats.sch++; + } + + /* Alive notification via Rx interrupt will do the real work */ + if (inta & CSR_INT_BIT_ALIVE) { + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } + } +#endif + /* Safely ignore these bits for debug checks below */ + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); + + /* HW RF KILL switch toggled */ + if (inta & CSR_INT_BIT_RF_KILL) { + int hw_rf_kill = 0; + if (!(iwl_read32(priv, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) + hw_rf_kill = 1; + + IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", + hw_rf_kill ? "disable radio" : "enable radio"); + + priv->isr_stats.rfkill++; + + /* driver only loads ucode once setting the interface up. + * the driver allows loading the ucode even if the radio + * is killed. Hence update the killswitch state here. The + * rfkill handler will care about restarting if needed. + */ + if (!test_bit(STATUS_ALIVE, &priv->status)) { + if (hw_rf_kill) + set_bit(STATUS_RF_KILL_HW, &priv->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->status); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); + } + + handled |= CSR_INT_BIT_RF_KILL; + } + + /* Chip got too hot and stopped itself */ + if (inta & CSR_INT_BIT_CT_KILL) { + IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; + handled |= CSR_INT_BIT_CT_KILL; + } + + /* Error detected by uCode */ + if (inta & CSR_INT_BIT_SW_ERR) { + IWL_ERR(priv, "Microcode SW error detected. " + " Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + iwl_irq_handle_error(priv); + handled |= CSR_INT_BIT_SW_ERR; + } + + /* uCode wakes up after power-down sleep */ + if (inta & CSR_INT_BIT_WAKEUP) { + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); + iwl_rx_queue_update_write_ptr(priv, &priv->rxq); + for (i = 0; i < priv->hw_params.max_txq_num; i++) + iwl_txq_update_write_ptr(priv, &priv->txq[i]); + + priv->isr_stats.wakeup++; + + handled |= CSR_INT_BIT_WAKEUP; + } + + /* All uCode command responses, including Tx command responses, + * Rx "responses" (frame-received notification), and other + * notifications from uCode come through here*/ + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | + CSR_INT_BIT_RX_PERIODIC)) { + IWL_DEBUG_ISR(priv, "Rx interrupt\n"); + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { + handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); + iwl_write32(priv, CSR_FH_INT_STATUS, + CSR_FH_INT_RX_MASK); + } + if (inta & CSR_INT_BIT_RX_PERIODIC) { + handled |= CSR_INT_BIT_RX_PERIODIC; + iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); + } + /* Sending RX interrupt require many steps to be done in the + * the device: + * 1- write interrupt to current index in ICT table. + * 2- dma RX frame. + * 3- update RX shared data to indicate last write index. + * 4- send interrupt. + * This could lead to RX race, driver could receive RX interrupt + * but the shared data changes does not reflect this; + * periodic interrupt will detect any dangling Rx activity. + */ + + /* Disable periodic interrupt; we use it as just a one-shot. */ + iwl_write8(priv, CSR_INT_PERIODIC_REG, + CSR_INT_PERIODIC_DIS); + iwl_rx_handle(priv); + + /* + * Enable periodic interrupt in 8 msec only if we received + * real RX interrupt (instead of just periodic int), to catch + * any dangling Rx interrupt. If it was just the periodic + * interrupt, there was no dangling Rx activity, and no need + * to extend the periodic interrupt; one-shot is enough. + */ + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) + iwl_write8(priv, CSR_INT_PERIODIC_REG, + CSR_INT_PERIODIC_ENA); + + priv->isr_stats.rx++; + } + + /* This "Tx" DMA channel is used only for loading uCode */ + if (inta & CSR_INT_BIT_FH_TX) { + iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); + priv->isr_stats.tx++; + handled |= CSR_INT_BIT_FH_TX; + /* Wake up uCode load routine, now that load is complete */ + priv->ucode_write_complete = 1; + wake_up_interruptible(&priv->wait_command_queue); + } + + if (inta & ~handled) { + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } + + if (inta & ~(priv->inta_mask)) { + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", + inta & ~priv->inta_mask); + } + + /* Re-enable all interrupts */ + /* only Re-enable if disabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); + /* Re-enable RF_KILL if it occurred */ + else if (handled & CSR_INT_BIT_RF_KILL) + iwl_enable_rfkill_int(priv); +} + +/****************************************************************************** + * + * ICT functions + * + ******************************************************************************/ +#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) + +/* Free dram table */ +void iwl_free_isr_ict(struct iwl_priv *priv) +{ + if (priv->ict_tbl_vir) { + dma_free_coherent(priv->bus->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + priv->ict_tbl_vir, + priv->ict_tbl_dma); + priv->ict_tbl_vir = NULL; + memset(&priv->ict_tbl_dma, 0, + sizeof(priv->ict_tbl_dma)); + memset(&priv->aligned_ict_tbl_dma, 0, + sizeof(priv->aligned_ict_tbl_dma)); + } +} + + +/* allocate dram shared table it is a PAGE_SIZE aligned + * also reset all data related to ICT table interrupt. + */ +int iwl_alloc_isr_ict(struct iwl_priv *priv) +{ + + /* allocate shrared data table */ + priv->ict_tbl_vir = + dma_alloc_coherent(priv->bus->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + &priv->ict_tbl_dma, GFP_KERNEL); + if (!priv->ict_tbl_vir) + return -ENOMEM; + + /* align table to PAGE_SIZE boundary */ + priv->aligned_ict_tbl_dma = + ALIGN(priv->ict_tbl_dma, PAGE_SIZE); + + IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", + (unsigned long long)priv->ict_tbl_dma, + (unsigned long long)priv->aligned_ict_tbl_dma, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); + + priv->ict_tbl = priv->ict_tbl_vir + + (priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma); + + IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", + priv->ict_tbl, priv->ict_tbl_vir, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); + + /* reset table and index to all 0 */ + memset(priv->ict_tbl_vir, 0, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + priv->ict_index = 0; + + /* add periodic RX interrupt */ + priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; + return 0; +} + +/* Device is going up inform it about using ICT interrupt table, + * also we need to tell the driver to start using ICT interrupt. + */ +int iwl_reset_ict(struct iwl_priv *priv) +{ + u32 val; + unsigned long flags; + + if (!priv->ict_tbl_vir) + return 0; + + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + + memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + + val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; + + val |= CSR_DRAM_INT_TBL_ENABLE; + val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; + + IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " + "aligned dma address %Lx\n", + val, + (unsigned long long)priv->aligned_ict_tbl_dma); + + iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); + priv->use_ict = true; + priv->ict_index = 0; + iwl_write32(priv, CSR_INT, priv->inta_mask); + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +/* Device is going down disable ict interrupt usage */ +void iwl_disable_ict(struct iwl_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->use_ict = false; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static irqreturn_t iwl_isr(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; + unsigned long flags; +#ifdef CONFIG_IWLWIFI_DEBUG + u32 inta_fh; +#endif + if (!priv) + return IRQ_NONE; + + spin_lock_irqsave(&priv->lock, flags); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(priv, CSR_INT); + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!inta) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + goto none; + } + + if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { + /* Hardware disappeared. It might have already raised + * an interrupt */ + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + goto unplugged; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " + "fh 0x%08x\n", inta, inta_mask, inta_fh); + } +#endif + + priv->inta |= inta; + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta)) + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + !priv->inta) + iwl_enable_interrupts(priv); + + unplugged: + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. */ + /* only Re-enable if disabled by irq and no schedules tasklet. */ + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_NONE; +} + +/* interrupt handler using ict table, with this interrupt driver will + * stop using INTA register to get device's interrupt, reading this register + * is expensive, device will write interrupts in ICT dram table, increment + * index then will fire interrupt to driver, driver will OR all ICT table + * entries from current index up to table entry with 0 value. the result is + * the interrupt we need to service, driver will set the entries back to 0 and + * set index. + */ +irqreturn_t iwl_isr_ict(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; + u32 val = 0; + unsigned long flags; + + if (!priv) + return IRQ_NONE; + + /* dram interrupt table not set yet, + * use legacy interrupt. + */ + if (!priv->use_ict) + return iwl_isr(irq, data); + + spin_lock_irqsave(&priv->lock, flags); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. + */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!priv->ict_tbl[priv->ict_index]) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + goto none; + } + + /* read all entries that not 0 start with ict_index */ + while (priv->ict_tbl[priv->ict_index]) { + + val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); + IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", + priv->ict_index, + le32_to_cpu( + priv->ict_tbl[priv->ict_index])); + priv->ict_tbl[priv->ict_index] = 0; + priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, + ICT_COUNT); + + } + + /* We should not get this value, just ignore it. */ + if (val == 0xffffffff) + val = 0; + + /* + * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit + * (bit 15 before shifting it to 31) to clear when using interrupt + * coalescing. fortunately, bits 18 and 19 stay set when this happens + * so we use them to decide on the real state of the Rx bit. + * In order words, bit 15 is set if bit 18 or bit 19 are set. + */ + if (val & 0xC0000) + val |= 0x8000; + + inta = (0xff & val) | ((0xff00 & val) << 16); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", + inta, inta_mask, val); + + inta &= priv->inta_mask; + priv->inta |= inta; + + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta)) + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + !priv->inta) { + /* Allow interrupt if was disabled by this handler and + * no tasklet was schedules, We should not enable interrupt, + * tasklet will enable it. + */ + iwl_enable_interrupts(priv); + } + + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. + * only Re-enable if disabled by irq. + */ + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_NONE; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 9b07e07..a6b2b1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -26,18 +26,58 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ - #include <linux/etherdevice.h> -#include <linux/sched.h> #include <linux/slab.h> +#include <linux/sched.h> #include <net/mac80211.h> -#include "iwl-eeprom.h" + #include "iwl-agn.h" #include "iwl-dev.h" #include "iwl-core.h" -#include "iwl-sta.h" #include "iwl-io.h" #include "iwl-helpers.h" +#include "iwl-trans-int-pcie.h" + +/** + * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array + */ +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + u16 byte_cnt) +{ + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + int write_ptr = txq->q.write_ptr; + int txq_id = txq->q.id; + u8 sec_ctl = 0; + u8 sta_id = 0; + u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; + __le16 bc_ent; + + WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); + + sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; + + switch (sec_ctl & TX_CMD_SEC_MSK) { + case TX_CMD_SEC_CCM: + len += CCMP_MIC_LEN; + break; + case TX_CMD_SEC_TKIP: + len += TKIP_ICV_LEN; + break; + case TX_CMD_SEC_WEP: + len += WEP_IV_LEN + WEP_ICV_LEN; + break; + } + + bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); + + scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; + + if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; +} /** * iwl_txq_update_write_ptr - Send new write index to hardware @@ -126,7 +166,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) } static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, - struct iwl_tfd *tfd, enum dma_data_direction dma_dir) + struct iwl_tfd *tfd, enum dma_data_direction dma_dir) { int i; int num_tbs; @@ -142,14 +182,14 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, /* Unmap tx_cmd */ if (num_tbs) - dma_unmap_single(priv->bus.dev, + dma_unmap_single(priv->bus->dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(priv->bus.dev, iwl_tfd_tb_get_addr(tfd, i), + dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); } @@ -292,6 +332,187 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, return 0; } +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too. + * Add a declaration to make sparse happy */ +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); + +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; + int txq_id = txq->q.id; + int read_ptr = txq->q.read_ptr; + u8 sta_id = 0; + __le16 bc_ent; + + WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); + + if (txq_id != priv->cmd_queue) + sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; + + bc_ent = cpu_to_le16(1 | (sta_id << 12)); + scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; + + if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; +} + +static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, + u16 txq_id) +{ + u32 tbl_dw_addr; + u32 tbl_dw; + u16 scd_q2ratid; + + scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; + + tbl_dw_addr = priv->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); + + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); + + if (txq_id & 0x1) + tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); + else + tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); + + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); + + return 0; +} + +static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) +{ + /* Simply stop the queue, but don't change any configuration; + * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ + iwl_write_prph(priv, + SCD_QUEUE_STATUS_BITS(txq_id), + (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); +} + +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index) +{ + iwl_write_direct32(priv, HBUS_TARG_WRPTR, + (index & 0xff) | (txq_id << 8)); + iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); +} + +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + int tx_fifo_id, int scd_retry) +{ + int txq_id = txq->q.id; + int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; + + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), + (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | + (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << SCD_QUEUE_STTS_REG_POS_WSL) | + SCD_QUEUE_STTS_REG_MSK); + + txq->sched_retry = scd_retry; + + IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", + active ? "Activate" : "Deactivate", + scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); +} + +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit) +{ + int tx_fifo, txq_id, ssn_idx; + u16 ra_tid; + unsigned long flags; + struct iwl_tid_data *tid_data; + + if (WARN_ON(sta_id == IWL_INVALID_STATION)) + return; + if (WARN_ON(tid >= MAX_TID_COUNT)) + return; + + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + ssn_idx = SEQ_TO_SN(tid_data->seq_number); + txq_id = tid_data->agg.txq_id; + tx_fifo = tid_data->agg.tx_fifo; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ra_tid = BUILD_RAxTID(sta_id, tid); + + spin_lock_irqsave(&priv->lock, flags); + + /* Stop this Tx queue before configuring it */ + iwlagn_tx_queue_stop_scheduler(priv, txq_id); + + /* Map receiver-address / traffic-ID to this queue */ + iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); + + /* Set this queue as a chain-building queue */ + iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<<txq_id)); + + /* enable aggregations for the queue */ + iwl_set_bits_prph(priv, SCD_AGGR_SEL, (1<<txq_id)); + + /* Place first TFD at index corresponding to start sequence number. + * Assumes that ssn_idx is valid (!= 0xFFF) */ + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); + + /* Set up Tx window size and frame limit for this queue */ + iwl_write_targ_mem(priv, priv->scd_base_addr + + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + + sizeof(u32), + ((frame_limit << + SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((frame_limit << + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + + iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + + /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + IWL_ERR(priv, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues - 1); + return -EINVAL; + } + + iwlagn_tx_queue_stop_scheduler(priv, txq_id); + + iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); + + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); + + iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv, txq_id); + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + + return 0; +} + /*************** HOST COMMAND QUEUE FUNCTIONS *****/ /** @@ -303,7 +524,7 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, * failed. On success, it turns the index (> 0) of command in the * command queue. */ -int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; @@ -419,9 +640,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) le16_to_cpu(out_cmd->hdr.sequence), cmd_size, q->write_ptr, idx, priv->cmd_queue); - phys_addr = dma_map_single(priv->bus.dev, &out_cmd->hdr, copy_size, + phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) { + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { idx = -ENOMEM; goto out; } @@ -441,9 +662,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) continue; if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; - phys_addr = dma_map_single(priv->bus.dev, (void *)cmd->data[i], + phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i], cmd->len[i], DMA_BIDIRECTIONAL); - if (dma_mapping_error(priv->bus.dev, phys_addr)) { + if (dma_mapping_error(priv->bus->dev, phys_addr)) { iwlagn_unmap_tfd(priv, out_meta, &txq->tfds[q->write_ptr], DMA_BIDIRECTIONAL); @@ -574,3 +795,242 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) spin_unlock_irqrestore(&priv->hcmd_lock, flags); } + +const char *get_cmd_string(u8 cmd) +{ + switch (cmd) { + IWL_CMD(REPLY_ALIVE); + IWL_CMD(REPLY_ERROR); + IWL_CMD(REPLY_RXON); + IWL_CMD(REPLY_RXON_ASSOC); + IWL_CMD(REPLY_QOS_PARAM); + IWL_CMD(REPLY_RXON_TIMING); + IWL_CMD(REPLY_ADD_STA); + IWL_CMD(REPLY_REMOVE_STA); + IWL_CMD(REPLY_REMOVE_ALL_STA); + IWL_CMD(REPLY_TXFIFO_FLUSH); + IWL_CMD(REPLY_WEPKEY); + IWL_CMD(REPLY_TX); + IWL_CMD(REPLY_LEDS_CMD); + IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); + IWL_CMD(COEX_PRIORITY_TABLE_CMD); + IWL_CMD(COEX_MEDIUM_NOTIFICATION); + IWL_CMD(COEX_EVENT_CMD); + IWL_CMD(REPLY_QUIET_CMD); + IWL_CMD(REPLY_CHANNEL_SWITCH); + IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); + IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); + IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); + IWL_CMD(POWER_TABLE_CMD); + IWL_CMD(PM_SLEEP_NOTIFICATION); + IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); + IWL_CMD(REPLY_SCAN_CMD); + IWL_CMD(REPLY_SCAN_ABORT_CMD); + IWL_CMD(SCAN_START_NOTIFICATION); + IWL_CMD(SCAN_RESULTS_NOTIFICATION); + IWL_CMD(SCAN_COMPLETE_NOTIFICATION); + IWL_CMD(BEACON_NOTIFICATION); + IWL_CMD(REPLY_TX_BEACON); + IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); + IWL_CMD(QUIET_NOTIFICATION); + IWL_CMD(REPLY_TX_PWR_TABLE_CMD); + IWL_CMD(MEASURE_ABORT_NOTIFICATION); + IWL_CMD(REPLY_BT_CONFIG); + IWL_CMD(REPLY_STATISTICS_CMD); + IWL_CMD(STATISTICS_NOTIFICATION); + IWL_CMD(REPLY_CARD_STATE_CMD); + IWL_CMD(CARD_STATE_NOTIFICATION); + IWL_CMD(MISSED_BEACONS_NOTIFICATION); + IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); + IWL_CMD(SENSITIVITY_CMD); + IWL_CMD(REPLY_PHY_CALIBRATION_CMD); + IWL_CMD(REPLY_RX_PHY_CMD); + IWL_CMD(REPLY_RX_MPDU_CMD); + IWL_CMD(REPLY_RX); + IWL_CMD(REPLY_COMPRESSED_BA); + IWL_CMD(CALIBRATION_CFG_CMD); + IWL_CMD(CALIBRATION_RES_NOTIFICATION); + IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); + IWL_CMD(REPLY_TX_POWER_DBM_CMD); + IWL_CMD(TEMPERATURE_NOTIFICATION); + IWL_CMD(TX_ANT_CONFIGURATION_CMD); + IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); + IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); + IWL_CMD(REPLY_BT_COEX_PROT_ENV); + IWL_CMD(REPLY_WIPAN_PARAMS); + IWL_CMD(REPLY_WIPAN_RXON); + IWL_CMD(REPLY_WIPAN_RXON_TIMING); + IWL_CMD(REPLY_WIPAN_RXON_ASSOC); + IWL_CMD(REPLY_WIPAN_QOS_PARAM); + IWL_CMD(REPLY_WIPAN_WEPKEY); + IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); + IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); + IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); + IWL_CMD(REPLY_WOWLAN_PATTERNS); + IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER); + IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS); + IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS); + IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL); + IWL_CMD(REPLY_WOWLAN_GET_STATUS); + default: + return "UNKNOWN"; + + } +} + +#define HOST_COMPLETE_TIMEOUT (2 * HZ) + +static void iwl_generic_cmd_callback(struct iwl_priv *priv, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt) +{ + if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { + IWL_ERR(priv, "Bad return from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + return; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + switch (cmd->hdr.cmd) { + case REPLY_TX_LINK_QUALITY_CMD: + case SENSITIVITY_CMD: + IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + break; + default: + IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + } +#endif +} + +static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + int ret; + + /* An asynchronous command can not expect an SKB to be set. */ + if (WARN_ON(cmd->flags & CMD_WANT_SKB)) + return -EINVAL; + + /* Assign a generic callback if one is not provided */ + if (!cmd->callback) + cmd->callback = iwl_generic_cmd_callback; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return -EBUSY; + + ret = iwl_enqueue_hcmd(priv, cmd); + if (ret < 0) { + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", + get_cmd_string(cmd->id), ret); + return ret; + } + return 0; +} + +static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + int cmd_idx; + int ret; + + lockdep_assert_held(&priv->mutex); + + /* A synchronous command can not have a callback set. */ + if (WARN_ON(cmd->callback)) + return -EINVAL; + + IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", + get_cmd_string(cmd->id)); + + set_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", + get_cmd_string(cmd->id)); + + cmd_idx = iwl_enqueue_hcmd(priv, cmd); + if (cmd_idx < 0) { + ret = cmd_idx; + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", + get_cmd_string(cmd->id), ret); + return ret; + } + + ret = wait_event_interruptible_timeout(priv->wait_command_queue, + !test_bit(STATUS_HCMD_ACTIVE, &priv->status), + HOST_COMPLETE_TIMEOUT); + if (!ret) { + if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { + IWL_ERR(priv, + "Error sending %s: time out after %dms.\n", + get_cmd_string(cmd->id), + jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); + + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command" + "%s\n", get_cmd_string(cmd->id)); + ret = -ETIMEDOUT; + goto cancel; + } + } + + if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { + IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", + get_cmd_string(cmd->id)); + ret = -ECANCELED; + goto fail; + } + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_ERR(priv, "Command %s failed: FW Error\n", + get_cmd_string(cmd->id)); + ret = -EIO; + goto fail; + } + if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { + IWL_ERR(priv, "Error: Response NULL in '%s'\n", + get_cmd_string(cmd->id)); + ret = -EIO; + goto cancel; + } + + return 0; + +cancel: + if (cmd->flags & CMD_WANT_SKB) { + /* + * Cancel the CMD_WANT_SKB flag for the cmd in the + * TX cmd queue. Otherwise in case the cmd comes + * in later, it will possibly set an invalid + * address (cmd->meta.source). + */ + priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= + ~CMD_WANT_SKB; + } +fail: + if (cmd->reply_page) { + iwl_free_pages(priv, cmd->reply_page); + cmd->reply_page = 0; + } + + return ret; +} + +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + if (cmd->flags & CMD_ASYNC) + return iwl_send_cmd_async(priv, cmd); + + return iwl_send_cmd_sync(priv, cmd); +} + +int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + const void *data) +{ + struct iwl_host_cmd cmd = { + .id = id, + .len = { len, }, + .data = { data, }, + .flags = flags, + }; + + return iwl_send_cmd(priv, &cmd); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index d760857..41f0de9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -64,6 +64,7 @@ #include "iwl-trans.h" #include "iwl-core.h" #include "iwl-helpers.h" +#include "iwl-trans-int-pcie.h" /*TODO remove uneeded includes when the transport layer tx_free will be here */ #include "iwl-agn.h" #include "iwl-core.h" @@ -71,7 +72,7 @@ static int iwl_trans_rx_alloc(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; - struct device *dev = priv->bus.dev; + struct device *dev = priv->bus->dev; memset(&priv->rxq, 0, sizeof(priv->rxq)); @@ -117,7 +118,7 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) /* In the reset function, these buffers may have been allocated * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { - dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma, + dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); __iwl_free_pages(priv, rxq->pool[i].page); @@ -127,7 +128,56 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) } } -static int iwl_trans_rx_init(struct iwl_priv *priv) +static void iwl_trans_rx_hw_init(struct iwl_priv *priv, + struct iwl_rx_queue *rxq) +{ + u32 rb_size; + const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ + u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ + + rb_timeout = RX_RB_TIMEOUT; + + if (iwlagn_mod_params.amsdu_size_8K) + rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; + else + rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; + + /* Stop Rx DMA */ + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + + /* Reset driver's Rx queue write index */ + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + + /* Tell device where to find RBD circular buffer in DRAM */ + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, + (u32)(rxq->bd_dma >> 8)); + + /* Tell device where in DRAM to update its Rx status */ + iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, + rxq->rb_stts_dma >> 4); + + /* Enable Rx DMA + * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in + * the credit mechanism in 5000 HW RX FIFO + * Direct rx interrupts to hosts + * Rx buffer size 4 or 8k + * RB timeout 0x10 + * 256 RBDs + */ + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | + FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | + FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | + rb_size| + (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| + (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); + + /* Set interrupt coalescing timer to default (2048 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); +} + +static int iwl_rx_init(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; int i, err; @@ -155,6 +205,15 @@ static int iwl_trans_rx_init(struct iwl_priv *priv) rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); + iwlagn_rx_replenish(priv); + + iwl_trans_rx_hw_init(priv, rxq); + + spin_lock_irqsave(&priv->lock, flags); + rxq->need_update = 1; + iwl_rx_queue_update_write_ptr(priv, rxq); + spin_unlock_irqrestore(&priv->lock, flags); + return 0; } @@ -174,13 +233,13 @@ static void iwl_trans_rx_free(struct iwl_priv *priv) iwl_trans_rxq_free_rx_bufs(priv); spin_unlock_irqrestore(&rxq->lock, flags); - dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(priv->bus->dev, sizeof(__le32) * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; if (rxq->rb_stts) - dma_free_coherent(priv->bus.dev, + dma_free_coherent(priv->bus->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); else @@ -204,7 +263,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, if (WARN_ON(ptr->addr)) return -EINVAL; - ptr->addr = dma_alloc_coherent(priv->bus.dev, size, + ptr->addr = dma_alloc_coherent(priv->bus->dev, size, &ptr->dma, GFP_KERNEL); if (!ptr->addr) return -ENOMEM; @@ -218,7 +277,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, if (unlikely(!ptr->addr)) return; - dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } @@ -265,7 +324,7 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = dma_alloc_coherent(priv->bus.dev, tfd_sz, &txq->q.dma_addr, + txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL); if (!txq->tfds) { IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); @@ -356,7 +415,7 @@ static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct device *dev = priv->bus.dev; + struct device *dev = priv->bus->dev; int i; if (WARN_ON(!txq)) return; @@ -467,11 +526,11 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv) return 0; error: - trans_tx_free(priv); + trans_tx_free(&priv->trans); return ret; } -static int iwl_trans_tx_init(struct iwl_priv *priv) +static int iwl_tx_init(struct iwl_priv *priv) { int ret; int txq_id, slots_num; @@ -488,7 +547,7 @@ static int iwl_trans_tx_init(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 0); + iwl_write_prph(priv, SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); @@ -511,10 +570,308 @@ static int iwl_trans_tx_init(struct iwl_priv *priv) error: /*Upon error, free only if we allocated something */ if (alloc) - trans_tx_free(priv); + trans_tx_free(&priv->trans); + return ret; +} + +static void iwl_set_pwr_vmain(struct iwl_priv *priv) +{ +/* + * (for documentation purposes) + * to set power to V_AUX, do: + + if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VAUX, + ~APMG_PS_CTRL_MSK_PWR_SRC); + */ + + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); +} + +static int iwl_nic_init(struct iwl_priv *priv) +{ + unsigned long flags; + + /* nic_init */ + spin_lock_irqsave(&priv->lock, flags); + iwl_apm_init(priv); + + /* Set interrupt coalescing calibration timer to default (512 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); + + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_set_pwr_vmain(priv); + + priv->cfg->lib->nic_config(priv); + + /* Allocate the RX queue, or reset if it is already allocated */ + iwl_rx_init(priv); + + /* Allocate or reset and init all Tx and Command queues */ + if (iwl_tx_init(priv)) + return -ENOMEM; + + if (priv->cfg->base_params->shadow_reg_enable) { + /* enable shadow regs in HW */ + iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, + 0x800FFFFF); + } + + set_bit(STATUS_INIT, &priv->status); + + return 0; +} + +#define HW_READY_TIMEOUT (50) + +/* Note: returns poll_bit return value, which is >= 0 if success */ +static int iwl_set_hw_ready(struct iwl_priv *priv) +{ + int ret; + + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); + + /* See if we got it */ + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + HW_READY_TIMEOUT); + + IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); + return ret; +} + +/* Note: returns standard 0/-ERROR code */ +static int iwl_trans_prepare_card_hw(struct iwl_priv *priv) +{ + int ret; + + IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n"); + + ret = iwl_set_hw_ready(priv); + if (ret >= 0) + return 0; + + /* If HW is not ready, prepare the conditions to check again */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PREPARE); + + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, + CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); + + if (ret < 0) + return ret; + + /* HW should be ready by now, check again. */ + ret = iwl_set_hw_ready(priv); + if (ret >= 0) + return 0; return ret; } +static int iwl_trans_start_device(struct iwl_priv *priv) +{ + int ret; + + priv->ucode_owner = IWL_OWNERSHIP_DRIVER; + + if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && + iwl_trans_prepare_card_hw(priv)) { + IWL_WARN(priv, "Exit HW not ready\n"); + return -EIO; + } + + /* If platform's RF_KILL switch is NOT set to KILL */ + if (iwl_read32(priv, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); + else + set_bit(STATUS_RF_KILL_HW, &priv->status); + + if (iwl_is_rfkill(priv)) { + wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); + iwl_enable_interrupts(priv); + return -ERFKILL; + } + + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + + ret = iwl_nic_init(priv); + if (ret) { + IWL_ERR(priv, "Unable to init nic\n"); + return ret; + } + + /* make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + + /* clear (again), then enable host interrupts */ + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); + + /* really make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + + return 0; +} + +/* + * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask + * must be called under priv->lock and mac access + */ +static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask) +{ + iwl_write_prph(priv, SCD_TXFACT, mask); +} + +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, +}; + +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, +}; +static void iwl_trans_tx_start(struct iwl_priv *priv) +{ + const struct queue_to_fifo_ac *queue_to_fifo; + struct iwl_rxon_context *ctx; + u32 a; + unsigned long flags; + int i, chan; + u32 reg_val; + + spin_lock_irqsave(&priv->lock, flags); + + priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); + a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; + /* reset conext data memory */ + for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; + a += 4) + iwl_write_targ_mem(priv, a, 0); + /* reset tx status memory */ + for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; + a += 4) + iwl_write_targ_mem(priv, a, 0); + for (; a < priv->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + iwl_write_targ_mem(priv, a, 0); + + iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, + priv->scd_bc_tbls.dma >> 10); + + /* Enable DMA channel */ + for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); + + /* Update FH chicken bits */ + reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, + reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); + + iwl_write_prph(priv, SCD_QUEUECHAIN_SEL, + SCD_QUEUECHAIN_SEL_ALL(priv)); + iwl_write_prph(priv, SCD_AGGR_SEL, 0); + + /* initiate the queues */ + for (i = 0; i < priv->hw_params.max_txq_num; i++) { + iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(priv, priv->scd_base_addr + + SCD_CONTEXT_QUEUE_OFFSET(i), 0); + iwl_write_targ_mem(priv, priv->scd_base_addr + + SCD_CONTEXT_QUEUE_OFFSET(i) + + sizeof(u32), + ((SCD_WIN_SIZE << + SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & + SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | + ((SCD_FRAME_LIMIT << + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & + SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); + } + + iwl_write_prph(priv, SCD_INTERRUPT_MASK, + IWL_MASK(0, priv->hw_params.max_txq_num)); + + /* Activate all Tx DMA/FIFO channels */ + iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); + + /* map queues to FIFOs */ + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; + else + queue_to_fifo = iwlagn_default_queue_to_tx_fifo; + + iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0); + + /* make sure all queue are not stopped */ + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); + for (i = 0; i < 4; i++) + atomic_set(&priv->queue_stop_count[i], 0); + for_each_context(priv, ctx) + ctx->last_tx_rejected = false; + + /* reset to 0 to enable all the queue first */ + priv->txq_ctx_active_msk = 0; + + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); + + for (i = 0; i < 10; i++) { + int fifo = queue_to_fifo[i].fifo; + int ac = queue_to_fifo[i].ac; + + iwl_txq_ctx_activate(priv, i); + + if (fifo == IWL_TX_FIFO_UNUSED) + continue; + + if (ac != IWL_AC_UNSET) + iwl_set_swq_id(&priv->txq[i], ac, i); + iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Enable L1-Active */ + iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); +} + /** * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ @@ -526,7 +883,7 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) /* Turn off all Tx DMA fifos */ spin_lock_irqsave(&priv->lock, flags); - iwlagn_txq_set_sched(priv, 0); + iwl_trans_txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { @@ -552,20 +909,264 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) return 0; } +static void iwl_trans_stop_device(struct iwl_priv *priv) +{ + unsigned long flags; + + /* stop and reset the on-board processor */ + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + + /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + trans_sync_irq(&priv->trans); + + /* device going down, Stop using ICT table */ + iwl_disable_ict(priv); + + /* + * If a HW restart happens during firmware loading, + * then the firmware loading might call this function + * and later it might be called again due to the + * restart. So don't process again if the device is + * already dead. + */ + if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { + iwl_trans_tx_stop(priv); + iwl_trans_rx_stop(priv); + + /* Power-down device's busmaster DMA clocks */ + iwl_write_prph(priv, APMG_CLK_DIS_REG, + APMG_CLK_VAL_DMA_CLK_RQT); + udelay(5); + } + + /* Make sure (redundant) we've released our request to stay awake */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + + /* Stop the device, and put it in low power state */ + iwl_apm_stop(priv); +} + +static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv, + int txq_id) +{ + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_device_cmd *dev_cmd; + + if (unlikely(iwl_queue_space(q) < q->high_mark)) + return NULL; + + /* + * Set up the Tx-command (not MAC!) header. + * Store the chosen Tx queue and TFD index within the sequence field; + * after Tx, uCode's Tx response will return this value so driver can + * locate the frame within the tx queue and do post-tx processing. + */ + dev_cmd = txq->cmd[q->write_ptr]; + memset(dev_cmd, 0, sizeof(*dev_cmd)); + dev_cmd->hdr.cmd = REPLY_TX; + dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | + INDEX_TO_SEQ(q->write_ptr))); + return &dev_cmd->cmd.tx; +} + +static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx) +{ + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr]; + struct iwl_cmd_meta *out_meta; + + dma_addr_t phys_addr = 0; + dma_addr_t txcmd_phys; + dma_addr_t scratch_phys; + u16 len, firstlen, secondlen; + u8 wait_write_ptr = 0; + u8 hdr_len = ieee80211_hdrlen(fc); + + /* Set up driver data for this TFD */ + memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); + txq->txb[q->write_ptr].skb = skb; + txq->txb[q->write_ptr].ctx = ctx; + + /* Set up first empty entry in queue's array of Tx/cmd buffers */ + out_meta = &txq->meta[q->write_ptr]; + + /* + * Use the first empty entry in this queue's command buffer array + * to contain the Tx command and MAC header concatenated together + * (payload data will be in another buffer). + * Size of this varies, due to varying MAC header length. + * If end is not dword aligned, we'll have 2 extra bytes at the end + * of the MAC header (device reads on dword boundaries). + * We'll tell device about this padding later. + */ + len = sizeof(struct iwl_tx_cmd) + + sizeof(struct iwl_cmd_header) + hdr_len; + firstlen = (len + 3) & ~3; + + /* Tell NIC about any 2-byte padding after MAC header */ + if (firstlen != len) + tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; + + /* Physical address of this Tx command's header (not MAC header!), + * within command buffer array. */ + txcmd_phys = dma_map_single(priv->bus->dev, + &dev_cmd->hdr, firstlen, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys))) + return -1; + dma_unmap_addr_set(out_meta, mapping, txcmd_phys); + dma_unmap_len_set(out_meta, len, firstlen); + + if (!ieee80211_has_morefrags(fc)) { + txq->need_update = 1; + } else { + wait_write_ptr = 1; + txq->need_update = 0; + } + + /* Set up TFD's 2nd entry to point directly to remainder of skb, + * if any (802.11 null frames have no payload). */ + secondlen = skb->len - hdr_len; + if (secondlen > 0) { + phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len, + secondlen, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { + dma_unmap_single(priv->bus->dev, + dma_unmap_addr(out_meta, mapping), + dma_unmap_len(out_meta, len), + DMA_BIDIRECTIONAL); + return -1; + } + } + + /* Attach buffers to TFD */ + iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); + if (secondlen > 0) + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + secondlen, 0); + + scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + + offsetof(struct iwl_tx_cmd, scratch); + + /* take back ownership of DMA buffer to enable update */ + dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen, + DMA_BIDIRECTIONAL); + tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); + tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); + + IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", + le16_to_cpu(dev_cmd->hdr.sequence)); + IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + + /* Set up entry for this TFD in Tx byte-count array */ + if (ampdu) + iwl_trans_txq_update_byte_cnt_tbl(priv, txq, + le16_to_cpu(tx_cmd->len)); + + dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, + DMA_BIDIRECTIONAL); + + trace_iwlwifi_dev_tx(priv, + &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], + sizeof(struct iwl_tfd), + &dev_cmd->hdr, firstlen, + skb->data + hdr_len, secondlen); + + /* Tell device the write index *just past* this latest filled TFD */ + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); + iwl_txq_update_write_ptr(priv, txq); + + /* + * At this point the frame is "transmitted" successfully + * and we will get a TX status notification eventually, + * regardless of the value of ret. "ret" only indicates + * whether or not we should update the write pointer. + */ + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { + if (wait_write_ptr) { + txq->need_update = 1; + iwl_txq_update_write_ptr(priv, txq); + } else { + iwl_stop_queue(priv, txq); + } + } + return 0; +} + +static void iwl_trans_kick_nic(struct iwl_priv *priv) +{ + /* Remove all resets to allow NIC to operate */ + iwl_write32(priv, CSR_RESET, 0); +} + +static void iwl_trans_sync_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->bus->irq); + tasklet_kill(&priv->irq_tasklet); +} + +static void iwl_trans_free(struct iwl_priv *priv) +{ + free_irq(priv->bus->irq, priv); + iwl_free_isr_ict(priv); +} + static const struct iwl_trans_ops trans_ops = { - .rx_init = iwl_trans_rx_init, - .rx_stop = iwl_trans_rx_stop, - .rx_free = iwl_trans_rx_free, + .start_device = iwl_trans_start_device, + .prepare_card_hw = iwl_trans_prepare_card_hw, + .stop_device = iwl_trans_stop_device, - .tx_init = iwl_trans_tx_init, - .tx_stop = iwl_trans_tx_stop, + .tx_start = iwl_trans_tx_start, + + .rx_free = iwl_trans_rx_free, .tx_free = iwl_trans_tx_free, .send_cmd = iwl_send_cmd, .send_cmd_pdu = iwl_send_cmd_pdu, + + .get_tx_cmd = iwl_trans_get_tx_cmd, + .tx = iwl_trans_tx, + + .txq_agg_disable = iwl_trans_txq_agg_disable, + .txq_agg_setup = iwl_trans_txq_agg_setup, + + .kick_nic = iwl_trans_kick_nic, + + .sync_irq = iwl_trans_sync_irq, + .free = iwl_trans_free, }; -void iwl_trans_register(struct iwl_trans *trans) +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) { - trans->ops = &trans_ops; + int err; + + priv->trans.ops = &trans_ops; + priv->trans.priv = priv; + + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); + + iwl_alloc_isr_ict(priv); + + err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED, + DRV_NAME, priv); + if (err) { + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); + iwl_free_isr_ict(priv); + return err; + } + + INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); + + return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 111acca..7993aa7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -60,46 +60,166 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -static inline int trans_rx_init(struct iwl_priv *priv) +#ifndef __iwl_trans_h__ +#define __iwl_trans_h__ + + /*This file includes the declaration that are exported from the transport + * layer */ + +struct iwl_priv; +struct iwl_rxon_context; +struct iwl_host_cmd; + +/** + * struct iwl_trans_ops - transport specific operations + * @start_device: allocates and inits all the resources for the transport + * layer. + * @prepare_card_hw: claim the ownership on the HW. Will be called during + * probe. + * @tx_start: starts and configures all the Tx fifo - usually done once the fw + * is alive. + * @stop_device:stops the whole device (embedded CPU put to reset) + * @rx_free: frees the rx memory + * @tx_free: frees the tx memory + * @send_cmd:send a host command + * @send_cmd_pdu:send a host command: flags can be CMD_* + * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use + * @tx: send an skb + * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is + * ready and a successful ADDBA response has been received. + * @txq_agg_disable: de-configure a Tx queue to send AMPDUs + * @kick_nic: remove the RESET from the embedded CPU and let it run + * @sync_irq: the upper layer will typically disable interrupt and call this + * handler. After this handler returns, it is guaranteed that all + * the ISR / tasklet etc... have finished running and the transport + * layer shall not pass any Rx. + * @free: release all the ressource for the transport layer itself such as + * irq, tasklet etc... + */ +struct iwl_trans_ops { + + int (*start_device)(struct iwl_priv *priv); + int (*prepare_card_hw)(struct iwl_priv *priv); + void (*stop_device)(struct iwl_priv *priv); + void (*tx_start)(struct iwl_priv *priv); + void (*tx_free)(struct iwl_priv *priv); + void (*rx_free)(struct iwl_priv *priv); + + int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); + + int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + const void *data); + struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); + int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx); + + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); + void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); + + void (*kick_nic)(struct iwl_priv *priv); + + void (*sync_irq)(struct iwl_priv *priv); + void (*free)(struct iwl_priv *priv); +}; + +struct iwl_trans { + const struct iwl_trans_ops *ops; + struct iwl_priv *priv; +}; + +static inline int trans_start_device(struct iwl_trans *trans) { - return priv->trans.ops->rx_init(priv); + return trans->ops->start_device(trans->priv); } -static inline int trans_rx_stop(struct iwl_priv *priv) +static inline int trans_prepare_card_hw(struct iwl_trans *trans) { - return priv->trans.ops->rx_stop(priv); + return trans->ops->prepare_card_hw(trans->priv); } -static inline void trans_rx_free(struct iwl_priv *priv) +static inline void trans_stop_device(struct iwl_trans *trans) { - priv->trans.ops->rx_free(priv); + trans->ops->stop_device(trans->priv); } -static inline int trans_tx_init(struct iwl_priv *priv) +static inline void trans_tx_start(struct iwl_trans *trans) { - return priv->trans.ops->tx_init(priv); + trans->ops->tx_start(trans->priv); } -static inline int trans_tx_stop(struct iwl_priv *priv) +static inline void trans_rx_free(struct iwl_trans *trans) { - return priv->trans.ops->tx_stop(priv); + trans->ops->rx_free(trans->priv); } -static inline void trans_tx_free(struct iwl_priv *priv) +static inline void trans_tx_free(struct iwl_trans *trans) { - priv->trans.ops->tx_free(priv); + trans->ops->tx_free(trans->priv); } -static inline int trans_send_cmd(struct iwl_priv *priv, +static inline int trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - return priv->trans.ops->send_cmd(priv, cmd); + return trans->ops->send_cmd(trans->priv, cmd); } -static inline int trans_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, +static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, u16 len, const void *data) { - return priv->trans.ops->send_cmd_pdu(priv, id, flags, len, data); + return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data); +} + +static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans, + int txq_id) +{ + return trans->ops->get_tx_cmd(trans->priv, txq_id); } -void iwl_trans_register(struct iwl_trans *trans); +static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx) +{ + return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); +} + +static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + return trans->ops->txq_agg_disable(trans->priv, txq_id, + ssn_idx, tx_fifo); +} + +static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, + int tid, int frame_limit) +{ + trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit); +} + +static inline void trans_kick_nic(struct iwl_trans *trans) +{ + trans->ops->kick_nic(trans->priv); +} + +static inline void trans_sync_irq(struct iwl_trans *trans) +{ + trans->ops->sync_irq(trans->priv); +} + +static inline void trans_free(struct iwl_trans *trans) +{ + trans->ops->free(trans->priv); +} + +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv); + +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too */ + +struct iwl_tx_queue; +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); + +#endif /* __iwl_trans_h__ */ diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 76d018b..adb3490 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -44,9 +44,7 @@ struct lbs_private { /* Mesh */ struct net_device *mesh_dev; /* Virtual device */ #ifdef CONFIG_LIBERTAS_MESH - u32 mesh_connect_status; struct lbs_mesh_stats mstats; - int mesh_open; uint16_t mesh_tlv; u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 mesh_ssid_len; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index c79aac4b..94652c5 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -512,7 +512,7 @@ static int lbs_thread(void *data) if (priv->connect_status == LBS_CONNECTED) netif_wake_queue(priv->dev); if (priv->mesh_dev && - lbs_mesh_connected(priv)) + netif_running(priv->mesh_dev)) netif_wake_queue(priv->mesh_dev); } } diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 7969d10..be72c08 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -15,6 +15,121 @@ #include "cmd.h" +static int lbs_add_mesh(struct lbs_private *priv); + +/*************************************************************************** + * Mesh command handling + */ + +static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, + struct cmd_ds_mesh_access *cmd) +{ + int ret; + + lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); + + cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); + cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); + cmd->hdr.result = 0; + + cmd->action = cpu_to_le16(cmd_action); + + ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); + + lbs_deb_leave(LBS_DEB_CMD); + return ret; +} + +static int __lbs_mesh_config_send(struct lbs_private *priv, + struct cmd_ds_mesh_config *cmd, + uint16_t action, uint16_t type) +{ + int ret; + u16 command = CMD_MESH_CONFIG_OLD; + + lbs_deb_enter(LBS_DEB_CMD); + + /* + * Command id is 0xac for v10 FW along with mesh interface + * id in bits 14-13-12. + */ + if (priv->mesh_tlv == TLV_TYPE_MESH_ID) + command = CMD_MESH_CONFIG | + (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); + + cmd->hdr.command = cpu_to_le16(command); + cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); + cmd->hdr.result = 0; + + cmd->type = cpu_to_le16(type); + cmd->action = cpu_to_le16(action); + + ret = lbs_cmd_with_response(priv, command, cmd); + + lbs_deb_leave(LBS_DEB_CMD); + return ret; +} + +static int lbs_mesh_config_send(struct lbs_private *priv, + struct cmd_ds_mesh_config *cmd, + uint16_t action, uint16_t type) +{ + int ret; + + if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) + return -EOPNOTSUPP; + + ret = __lbs_mesh_config_send(priv, cmd, action, type); + return ret; +} + +/* This function is the CMD_MESH_CONFIG legacy function. It only handles the + * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG + * are all handled by preparing a struct cmd_ds_mesh_config and passing it to + * lbs_mesh_config_send. + */ +static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, + uint16_t chan) +{ + struct cmd_ds_mesh_config cmd; + struct mrvl_meshie *ie; + DECLARE_SSID_BUF(ssid); + + memset(&cmd, 0, sizeof(cmd)); + cmd.channel = cpu_to_le16(chan); + ie = (struct mrvl_meshie *)cmd.data; + + switch (action) { + case CMD_ACT_MESH_CONFIG_START: + ie->id = WLAN_EID_GENERIC; + ie->val.oui[0] = 0x00; + ie->val.oui[1] = 0x50; + ie->val.oui[2] = 0x43; + ie->val.type = MARVELL_MESH_IE_TYPE; + ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; + ie->val.version = MARVELL_MESH_IE_VERSION; + ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; + ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; + ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; + ie->val.mesh_id_len = priv->mesh_ssid_len; + memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); + ie->len = sizeof(struct mrvl_meshie_val) - + IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len; + cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); + break; + case CMD_ACT_MESH_CONFIG_STOP: + break; + default: + return -1; + } + lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", + action, priv->mesh_tlv, chan, + print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); + + return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); +} + + /*************************************************************************** * Mesh sysfs support */ @@ -155,17 +270,11 @@ static ssize_t lbs_mesh_set(struct device *dev, { struct lbs_private *priv = to_net_dev(dev)->ml_priv; int enable; - int ret, action = CMD_ACT_MESH_CONFIG_STOP; sscanf(buf, "%x", &enable); enable = !!enable; if (enable == !!priv->mesh_dev) return count; - if (enable) - action = CMD_ACT_MESH_CONFIG_START; - ret = lbs_mesh_config(priv, action, priv->channel); - if (ret) - return ret; if (enable) lbs_add_mesh(priv); @@ -200,582 +309,11 @@ static struct attribute *lbs_mesh_sysfs_entries[] = { NULL, }; -static struct attribute_group lbs_mesh_attr_group = { +static const struct attribute_group lbs_mesh_attr_group = { .attrs = lbs_mesh_sysfs_entries, }; - -/*************************************************************************** - * Initializing and starting, stopping mesh - */ - -/* - * Check mesh FW version and appropriately send the mesh start - * command - */ -int lbs_init_mesh(struct lbs_private *priv) -{ - struct net_device *dev = priv->dev; - int ret = 0; - - lbs_deb_enter(LBS_DEB_MESH); - - priv->mesh_connect_status = LBS_DISCONNECTED; - - /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ - /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ - /* 5.110.22 have mesh command with 0xa3 command id */ - /* 10.0.0.p0 FW brings in mesh config command with different id */ - /* Check FW version MSB and initialize mesh_fw_ver */ - if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { - /* Enable mesh, if supported, and work out which TLV it uses. - 0x100 + 291 is an unofficial value used in 5.110.20.pXX - 0x100 + 37 is the official value used in 5.110.21.pXX - but we check them in that order because 20.pXX doesn't - give an error -- it just silently fails. */ - - /* 5.110.20.pXX firmware will fail the command if the channel - doesn't match the existing channel. But only if the TLV - is correct. If the channel is wrong, _BOTH_ versions will - give an error to 0x100+291, and allow 0x100+37 to succeed. - It's just that 5.110.20.pXX will not have done anything - useful */ - - priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; - if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->channel)) { - priv->mesh_tlv = TLV_TYPE_MESH_ID; - if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->channel)) - priv->mesh_tlv = 0; - } - } else - if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && - (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { - /* 10.0.0.pXX new firmwares should succeed with TLV - * 0x100+37; Do not invoke command with old TLV. - */ - priv->mesh_tlv = TLV_TYPE_MESH_ID; - if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->channel)) - priv->mesh_tlv = 0; - } - - - if (priv->mesh_tlv) { - sprintf(priv->mesh_ssid, "mesh"); - priv->mesh_ssid_len = 4; - - lbs_add_mesh(priv); - - if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) - netdev_err(dev, "cannot register lbs_mesh attribute\n"); - - ret = 1; - } - - lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); - return ret; -} - - -int lbs_deinit_mesh(struct lbs_private *priv) -{ - struct net_device *dev = priv->dev; - int ret = 0; - - lbs_deb_enter(LBS_DEB_MESH); - - if (priv->mesh_tlv) { - device_remove_file(&dev->dev, &dev_attr_lbs_mesh); - ret = 1; - } - - lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); - return ret; -} - - -/** - * lbs_mesh_stop - close the mshX interface - * - * @dev: A pointer to &net_device structure - * returns: 0 - */ -static int lbs_mesh_stop(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_MESH); - spin_lock_irq(&priv->driver_lock); - - priv->mesh_open = 0; - priv->mesh_connect_status = LBS_DISCONNECTED; - - netif_stop_queue(dev); - netif_carrier_off(dev); - - spin_unlock_irq(&priv->driver_lock); - - schedule_work(&priv->mcast_work); - - lbs_deb_leave(LBS_DEB_MESH); - return 0; -} - -/** - * lbs_mesh_dev_open - open the mshX interface - * - * @dev: A pointer to &net_device structure - * returns: 0 or -EBUSY if monitor mode active - */ -static int lbs_mesh_dev_open(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - - lbs_deb_enter(LBS_DEB_NET); - - spin_lock_irq(&priv->driver_lock); - - if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { - ret = -EBUSY; - goto out; - } - - priv->mesh_open = 1; - priv->mesh_connect_status = LBS_CONNECTED; - netif_carrier_on(dev); - - if (!priv->tx_pending_len) - netif_wake_queue(dev); - out: - - spin_unlock_irq(&priv->driver_lock); - lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); - return ret; -} - -static const struct net_device_ops mesh_netdev_ops = { - .ndo_open = lbs_mesh_dev_open, - .ndo_stop = lbs_mesh_stop, - .ndo_start_xmit = lbs_hard_start_xmit, - .ndo_set_mac_address = lbs_set_mac_address, - .ndo_set_multicast_list = lbs_set_multicast_list, -}; - -/** - * lbs_add_mesh - add mshX interface - * - * @priv: A pointer to the &struct lbs_private structure - * returns: 0 if successful, -X otherwise - */ -int lbs_add_mesh(struct lbs_private *priv) -{ - struct net_device *mesh_dev = NULL; - int ret = 0; - - lbs_deb_enter(LBS_DEB_MESH); - - /* Allocate a virtual mesh device */ - mesh_dev = alloc_netdev(0, "msh%d", ether_setup); - if (!mesh_dev) { - lbs_deb_mesh("init mshX device failed\n"); - ret = -ENOMEM; - goto done; - } - mesh_dev->ml_priv = priv; - priv->mesh_dev = mesh_dev; - - mesh_dev->netdev_ops = &mesh_netdev_ops; - mesh_dev->ethtool_ops = &lbs_ethtool_ops; - memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN); - - SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); - - mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - /* Register virtual mesh interface */ - ret = register_netdev(mesh_dev); - if (ret) { - pr_err("cannot register mshX virtual interface\n"); - goto err_free; - } - - ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); - if (ret) - goto err_unregister; - - lbs_persist_config_init(mesh_dev); - - /* Everything successful */ - ret = 0; - goto done; - -err_unregister: - unregister_netdev(mesh_dev); - -err_free: - free_netdev(mesh_dev); - -done: - lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); - return ret; -} - -void lbs_remove_mesh(struct lbs_private *priv) -{ - struct net_device *mesh_dev; - - mesh_dev = priv->mesh_dev; - if (!mesh_dev) - return; - - lbs_deb_enter(LBS_DEB_MESH); - netif_stop_queue(mesh_dev); - netif_carrier_off(mesh_dev); - sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); - lbs_persist_config_remove(mesh_dev); - unregister_netdev(mesh_dev); - priv->mesh_dev = NULL; - free_netdev(mesh_dev); - lbs_deb_leave(LBS_DEB_MESH); -} - - - -/*************************************************************************** - * Sending and receiving - */ -struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, - struct net_device *dev, struct rxpd *rxpd) -{ - if (priv->mesh_dev) { - if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { - if (rxpd->rx_control & RxPD_MESH_FRAME) - dev = priv->mesh_dev; - } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { - if (rxpd->u.bss.bss_num == MESH_IFACE_ID) - dev = priv->mesh_dev; - } - } - return dev; -} - - -void lbs_mesh_set_txpd(struct lbs_private *priv, - struct net_device *dev, struct txpd *txpd) -{ - if (dev == priv->mesh_dev) { - if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) - txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); - else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) - txpd->u.bss.bss_num = MESH_IFACE_ID; - } -} - - -/*************************************************************************** - * Mesh command handling - */ - -/** - * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries - * - * @priv: A pointer to &struct lbs_private structure - * @add: TRUE to add the entry, FALSE to delete it - * @addr1: Destination address to blind or unblind - * - * returns: 0 on success, error on failure - */ -int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) -{ - struct cmd_ds_bt_access cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - BUG_ON(addr1 == NULL); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.addr1, addr1, ETH_ALEN); - if (add) { - cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD); - lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", - addr1, ETH_ALEN); - } else { - cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL); - lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", - addr1, ETH_ALEN); - } - - ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * lbs_mesh_bt_reset - Reset/clear the mesh blinding table - * - * @priv: A pointer to &struct lbs_private structure - * - * returns: 0 on success, error on failure - */ -int lbs_mesh_bt_reset(struct lbs_private *priv) -{ - struct cmd_ds_bt_access cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET); - - ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh - * blinding table - * - * Normally the firmware "blinds" or ignores traffic from mesh nodes in the - * table, but an inverted table allows *only* traffic from nodes listed in - * the table. - * - * @priv: A pointer to &struct lbs_private structure - * @inverted: On success, TRUE if the blinding table is inverted, - * FALSE if it is not inverted - * - * returns: 0 on success, error on failure - */ -int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) -{ - struct cmd_ds_bt_access cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - BUG_ON(inverted == NULL); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT); - - ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); - if (ret == 0) - *inverted = !!cmd.id; - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh - * blinding table - * - * Normally the firmware "blinds" or ignores traffic from mesh nodes in the - * table, but an inverted table allows *only* traffic from nodes listed in - * the table. - * - * @priv: A pointer to &struct lbs_private structure - * @inverted: TRUE to invert the blinding table (only traffic from - * listed nodes allowed), FALSE to return it - * to normal state (listed nodes ignored) - * - * returns: 0 on success, error on failure - */ -int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) -{ - struct cmd_ds_bt_access cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); - cmd.id = cpu_to_le32(!!inverted); - - ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table - * - * @priv: A pointer to &struct lbs_private structure - * @id: The ID of the entry to list - * @addr1: MAC address associated with the table entry - * - * returns: 0 on success, error on failure - */ -int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) -{ - struct cmd_ds_bt_access cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - BUG_ON(addr1 == NULL); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); - cmd.id = cpu_to_le32(id); - - ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); - if (ret == 0) - memcpy(addr1, cmd.addr1, sizeof(cmd.addr1)); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * lbs_cmd_fwt_access - Access the mesh forwarding table - * - * @priv: A pointer to &struct lbs_private structure - * @cmd_action: The forwarding table action to perform - * @cmd: The pre-filled FWT_ACCESS command - * - * returns: 0 on success and 'cmd' will be filled with the - * firmware's response - */ -int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, - struct cmd_ds_fwt_access *cmd) -{ - int ret; - - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); - - cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS); - cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access)); - cmd->hdr.result = 0; - cmd->action = cpu_to_le16(cmd_action); - - ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return 0; -} - -int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, - struct cmd_ds_mesh_access *cmd) -{ - int ret; - - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); - - cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); - cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); - cmd->hdr.result = 0; - - cmd->action = cpu_to_le16(cmd_action); - - ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -static int __lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type) -{ - int ret; - u16 command = CMD_MESH_CONFIG_OLD; - - lbs_deb_enter(LBS_DEB_CMD); - - /* - * Command id is 0xac for v10 FW along with mesh interface - * id in bits 14-13-12. - */ - if (priv->mesh_tlv == TLV_TYPE_MESH_ID) - command = CMD_MESH_CONFIG | - (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); - - cmd->hdr.command = cpu_to_le16(command); - cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); - cmd->hdr.result = 0; - - cmd->type = cpu_to_le16(type); - cmd->action = cpu_to_le16(action); - - ret = lbs_cmd_with_response(priv, command, cmd); - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -int lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type) -{ - int ret; - - if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) - return -EOPNOTSUPP; - - ret = __lbs_mesh_config_send(priv, cmd, action, type); - return ret; -} - -/* This function is the CMD_MESH_CONFIG legacy function. It only handles the - * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG - * are all handled by preparing a struct cmd_ds_mesh_config and passing it to - * lbs_mesh_config_send. - */ -int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) -{ - struct cmd_ds_mesh_config cmd; - struct mrvl_meshie *ie; - DECLARE_SSID_BUF(ssid); - - memset(&cmd, 0, sizeof(cmd)); - cmd.channel = cpu_to_le16(chan); - ie = (struct mrvl_meshie *)cmd.data; - - switch (action) { - case CMD_ACT_MESH_CONFIG_START: - ie->id = WLAN_EID_GENERIC; - ie->val.oui[0] = 0x00; - ie->val.oui[1] = 0x50; - ie->val.oui[2] = 0x43; - ie->val.type = MARVELL_MESH_IE_TYPE; - ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; - ie->val.version = MARVELL_MESH_IE_VERSION; - ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; - ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; - ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; - ie->val.mesh_id_len = priv->mesh_ssid_len; - memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); - ie->len = sizeof(struct mrvl_meshie_val) - - IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len; - cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); - break; - case CMD_ACT_MESH_CONFIG_STOP: - break; - default: - return -1; - } - lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", - action, priv->mesh_tlv, chan, - print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); - - return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); -} - - - /*************************************************************************** * Persistent configuration support */ @@ -1232,7 +770,7 @@ static struct attribute *boot_opts_attrs[] = { NULL }; -static struct attribute_group boot_opts_group = { +static const struct attribute_group boot_opts_group = { .name = "boot_options", .attrs = boot_opts_attrs, }; @@ -1245,31 +783,299 @@ static struct attribute *mesh_ie_attrs[] = { NULL }; -static struct attribute_group mesh_ie_group = { +static const struct attribute_group mesh_ie_group = { .name = "mesh_ie", .attrs = mesh_ie_attrs, }; -void lbs_persist_config_init(struct net_device *dev) +static void lbs_persist_config_init(struct net_device *dev) { int ret; ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); } -void lbs_persist_config_remove(struct net_device *dev) +static void lbs_persist_config_remove(struct net_device *dev) { sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); } +/*************************************************************************** + * Initializing and starting, stopping mesh + */ + +/* + * Check mesh FW version and appropriately send the mesh start + * command + */ +int lbs_init_mesh(struct lbs_private *priv) +{ + struct net_device *dev = priv->dev; + int ret = 0; + + lbs_deb_enter(LBS_DEB_MESH); + + /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ + /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ + /* 5.110.22 have mesh command with 0xa3 command id */ + /* 10.0.0.p0 FW brings in mesh config command with different id */ + /* Check FW version MSB and initialize mesh_fw_ver */ + if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { + /* Enable mesh, if supported, and work out which TLV it uses. + 0x100 + 291 is an unofficial value used in 5.110.20.pXX + 0x100 + 37 is the official value used in 5.110.21.pXX + but we check them in that order because 20.pXX doesn't + give an error -- it just silently fails. */ + + /* 5.110.20.pXX firmware will fail the command if the channel + doesn't match the existing channel. But only if the TLV + is correct. If the channel is wrong, _BOTH_ versions will + give an error to 0x100+291, and allow 0x100+37 to succeed. + It's just that 5.110.20.pXX will not have done anything + useful */ + + priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; + if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, + priv->channel)) { + priv->mesh_tlv = TLV_TYPE_MESH_ID; + if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, + priv->channel)) + priv->mesh_tlv = 0; + } + } else + if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && + (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { + /* 10.0.0.pXX new firmwares should succeed with TLV + * 0x100+37; Do not invoke command with old TLV. + */ + priv->mesh_tlv = TLV_TYPE_MESH_ID; + if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, + priv->channel)) + priv->mesh_tlv = 0; + } + + /* Stop meshing until interface is brought up */ + lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel); + + if (priv->mesh_tlv) { + sprintf(priv->mesh_ssid, "mesh"); + priv->mesh_ssid_len = 4; + + lbs_add_mesh(priv); + + if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) + netdev_err(dev, "cannot register lbs_mesh attribute\n"); + + ret = 1; + } + + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; +} + + +int lbs_deinit_mesh(struct lbs_private *priv) +{ + struct net_device *dev = priv->dev; + int ret = 0; + + lbs_deb_enter(LBS_DEB_MESH); + + if (priv->mesh_tlv) { + device_remove_file(&dev->dev, &dev_attr_lbs_mesh); + ret = 1; + } + + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; +} + + +/** + * lbs_mesh_stop - close the mshX interface + * + * @dev: A pointer to &net_device structure + * returns: 0 + */ +static int lbs_mesh_stop(struct net_device *dev) +{ + struct lbs_private *priv = dev->ml_priv; + + lbs_deb_enter(LBS_DEB_MESH); + lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel); + + spin_lock_irq(&priv->driver_lock); + + netif_stop_queue(dev); + netif_carrier_off(dev); + + spin_unlock_irq(&priv->driver_lock); + + schedule_work(&priv->mcast_work); + + lbs_deb_leave(LBS_DEB_MESH); + return 0; +} + +/** + * lbs_mesh_dev_open - open the mshX interface + * + * @dev: A pointer to &net_device structure + * returns: 0 or -EBUSY if monitor mode active + */ +static int lbs_mesh_dev_open(struct net_device *dev) +{ + struct lbs_private *priv = dev->ml_priv; + int ret = 0; + + lbs_deb_enter(LBS_DEB_NET); + + spin_lock_irq(&priv->driver_lock); + + if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { + ret = -EBUSY; + spin_unlock_irq(&priv->driver_lock); + goto out; + } + + netif_carrier_on(dev); + + if (!priv->tx_pending_len) + netif_wake_queue(dev); + + spin_unlock_irq(&priv->driver_lock); + + ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel); + +out: + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); + return ret; +} + +static const struct net_device_ops mesh_netdev_ops = { + .ndo_open = lbs_mesh_dev_open, + .ndo_stop = lbs_mesh_stop, + .ndo_start_xmit = lbs_hard_start_xmit, + .ndo_set_mac_address = lbs_set_mac_address, + .ndo_set_multicast_list = lbs_set_multicast_list, +}; + +/** + * lbs_add_mesh - add mshX interface + * + * @priv: A pointer to the &struct lbs_private structure + * returns: 0 if successful, -X otherwise + */ +static int lbs_add_mesh(struct lbs_private *priv) +{ + struct net_device *mesh_dev = NULL; + int ret = 0; + + lbs_deb_enter(LBS_DEB_MESH); + + /* Allocate a virtual mesh device */ + mesh_dev = alloc_netdev(0, "msh%d", ether_setup); + if (!mesh_dev) { + lbs_deb_mesh("init mshX device failed\n"); + ret = -ENOMEM; + goto done; + } + mesh_dev->ml_priv = priv; + priv->mesh_dev = mesh_dev; + + mesh_dev->netdev_ops = &mesh_netdev_ops; + mesh_dev->ethtool_ops = &lbs_ethtool_ops; + memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN); + + SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); + + mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + /* Register virtual mesh interface */ + ret = register_netdev(mesh_dev); + if (ret) { + pr_err("cannot register mshX virtual interface\n"); + goto err_free; + } + + ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); + if (ret) + goto err_unregister; + + lbs_persist_config_init(mesh_dev); + + /* Everything successful */ + ret = 0; + goto done; + +err_unregister: + unregister_netdev(mesh_dev); + +err_free: + free_netdev(mesh_dev); + +done: + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; +} + +void lbs_remove_mesh(struct lbs_private *priv) +{ + struct net_device *mesh_dev; + + mesh_dev = priv->mesh_dev; + if (!mesh_dev) + return; + + lbs_deb_enter(LBS_DEB_MESH); + netif_stop_queue(mesh_dev); + netif_carrier_off(mesh_dev); + sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); + lbs_persist_config_remove(mesh_dev); + unregister_netdev(mesh_dev); + priv->mesh_dev = NULL; + free_netdev(mesh_dev); + lbs_deb_leave(LBS_DEB_MESH); +} + + +/*************************************************************************** + * Sending and receiving + */ +struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, + struct net_device *dev, struct rxpd *rxpd) +{ + if (priv->mesh_dev) { + if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { + if (rxpd->rx_control & RxPD_MESH_FRAME) + dev = priv->mesh_dev; + } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { + if (rxpd->u.bss.bss_num == MESH_IFACE_ID) + dev = priv->mesh_dev; + } + } + return dev; +} + + +void lbs_mesh_set_txpd(struct lbs_private *priv, + struct net_device *dev, struct txpd *txpd) +{ + if (dev == priv->mesh_dev) { + if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) + txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); + else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) + txpd->u.bss.bss_num = MESH_IFACE_ID; + } +} + /*************************************************************************** * Ethtool related */ -static const char *mesh_stat_strings[] = { +static const char * const mesh_stat_strings[] = { "drop_duplicate_bcast", "drop_ttl_zero", "drop_no_fwd_route", diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index ee95c73..5014491 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h @@ -31,7 +31,6 @@ struct lbs_private; int lbs_init_mesh(struct lbs_private *priv); int lbs_deinit_mesh(struct lbs_private *priv); -int lbs_add_mesh(struct lbs_private *priv); void lbs_remove_mesh(struct lbs_private *priv); @@ -52,29 +51,6 @@ struct cmd_ds_command; struct cmd_ds_mesh_access; struct cmd_ds_mesh_config; -int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1); -int lbs_mesh_bt_reset(struct lbs_private *priv); -int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted); -int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted); -int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1); - -int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, - struct cmd_ds_fwt_access *cmd); - -int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, - struct cmd_ds_mesh_access *cmd); -int lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type); -int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); - - - -/* Persistent configuration */ - -void lbs_persist_config_init(struct net_device *net); -void lbs_persist_config_remove(struct net_device *net); - /* Ethtool statistics */ @@ -87,11 +63,6 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, uint32_t stringset, uint8_t *s); -/* Accessors */ - -#define lbs_mesh_open(priv) (priv->mesh_open) -#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED) - #else #define lbs_init_mesh(priv) @@ -101,8 +72,6 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, #define lbs_mesh_set_dev(priv, dev, rxpd) (dev) #define lbs_mesh_set_txpd(priv, dev, txpd) #define lbs_mesh_config(priv, enable, chan) -#define lbs_mesh_open(priv) (0) -#define lbs_mesh_connected(priv) (0) #endif diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index f19495b..a6e8513 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -199,7 +199,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) if (priv->connect_status == LBS_CONNECTED) netif_wake_queue(priv->dev); - if (priv->mesh_dev && lbs_mesh_connected(priv)) + if (priv->mesh_dev && netif_running(priv->mesh_dev)) netif_wake_queue(priv->mesh_dev); } EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 1bcf9ea..d26a78b 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -216,28 +216,19 @@ mwifiex_info_read(struct file *file, char __user *ubuf, p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); p += sprintf(p, "media_state=\"%s\"\n", (!priv->media_connected ? "Disconnected" : "Connected")); - p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", - netdev->dev_addr[0], netdev->dev_addr[1], - netdev->dev_addr[2], netdev->dev_addr[3], - netdev->dev_addr[4], netdev->dev_addr[5]); + p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr); if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", netdev_mc_count(netdev)); p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); - p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", - info.bssid[0], info.bssid[1], - info.bssid[2], info.bssid[3], - info.bssid[4], info.bssid[5]); + p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "region_code = \"%02x\"\n", info.region_code); netdev_for_each_mc_addr(ha, netdev) - p += sprintf(p, "multicast_address[%d]=" - "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++, - ha->addr[0], ha->addr[1], - ha->addr[2], ha->addr[3], - ha->addr[4], ha->addr[5]); + p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", + i++, ha->addr); } p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); @@ -451,26 +442,18 @@ mwifiex_debug_read(struct file *file, char __user *ubuf, if (info.tx_tbl_num) { p += sprintf(p, "Tx BA stream table:\n"); for (i = 0; i < info.tx_tbl_num; i++) - p += sprintf(p, "tid = %d, " - "ra = %02x:%02x:%02x:%02x:%02x:%02x\n", - info.tx_tbl[i].tid, info.tx_tbl[i].ra[0], - info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2], - info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4], - info.tx_tbl[i].ra[5]); + p += sprintf(p, "tid = %d, ra = %pM\n", + info.tx_tbl[i].tid, info.tx_tbl[i].ra); } if (info.rx_tbl_num) { p += sprintf(p, "Rx reorder table:\n"); for (i = 0; i < info.rx_tbl_num; i++) { - - p += sprintf(p, "tid = %d, " - "ta = %02x:%02x:%02x:%02x:%02x:%02x, " + p += sprintf(p, "tid = %d, ta = %pM, " "start_win = %d, " "win_size = %d, buffer: ", info.rx_tbl[i].tid, - info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1], - info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3], - info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5], + info.rx_tbl[i].ta, info.rx_tbl[i].start_win, info.rx_tbl[i].win_size); diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 7c1c5ee..f6bcc86 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -249,6 +249,7 @@ struct mwifiex_ds_hs_cfg { }; #define DEEP_SLEEP_ON 1 +#define DEEP_SLEEP_OFF 0 #define DEEP_SLEEP_IDLE_TIME 100 #define PS_MODE_AUTO 1 diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 03691c0..2215c3c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -929,6 +929,7 @@ int mwifiex_set_hs_params(struct mwifiex_private *priv, struct mwifiex_ds_hs_cfg *hscfg); int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); int mwifiex_enable_hs(struct mwifiex_adapter *adapter); +int mwifiex_disable_auto_ds(struct mwifiex_private *priv); int mwifiex_get_signal_info(struct mwifiex_private *priv, struct mwifiex_ds_get_signal *signal); int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 711fa68..82098ac 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -133,6 +133,9 @@ mwifiex_sdio_remove(struct sdio_func *func) adapter->priv[i]->media_connected) mwifiex_deauthenticate(adapter->priv[i], NULL); + mwifiex_disable_auto_ds(mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_ANY)); + mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), MWIFIEX_FUNC_SHUTDOWN); @@ -1319,7 +1322,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port)) || !MP_TX_AGGR_BUF_HAS_ROOM( - card, next_pkt_len)) + card, pkt_len + next_pkt_len)) f_send_aggr_buf = 1; } else { /* No room in Aggr buf, send it */ diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index d05907d..c34ff8c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -487,6 +487,20 @@ int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, } /* + * The function disables auto deep sleep mode. + */ +int mwifiex_disable_auto_ds(struct mwifiex_private *priv) +{ + struct mwifiex_ds_auto_ds auto_ds; + + auto_ds.auto_ds = DEEP_SLEEP_OFF; + + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, + DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds); +} +EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds); + +/* * IOCTL request handler to set/get active channel. * * This function performs validity checking on channel/frequency diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 67b2d0b..69e260b 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -634,6 +634,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, ra_list = NULL; } else { memcpy(ra, skb->data, ETH_ALEN); + if (ra[0] & 0x01) + memset(ra, 0xff, ETH_ALEN); ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d633edb..da36dbf 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1892,9 +1892,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txpriority = index; - if (ieee80211_is_data_qos(wh->frame_control) && - skb->protocol != cpu_to_be16(ETH_P_PAE) && - sta->ht_cap.ht_supported && priv->ap_fw) { + if (priv->ap_fw && sta && sta->ht_cap.ht_supported + && skb->protocol != cpu_to_be16(ETH_P_PAE) + && ieee80211_is_data_qos(wh->frame_control)) { tid = qos & 0xf; mwl8k_tx_count_packet(sta, tid); spin_lock(&priv->stream_lock); diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index 4a0a0e5..0ca8b145 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -150,7 +150,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match) struct orinoco_private *priv; struct airport *card; unsigned long phys_addr; - hermes_t *hw; + struct hermes *hw; if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) { printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n"); @@ -228,10 +228,9 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); MODULE_LICENSE("Dual MPL/GPL"); -static struct of_device_id airport_match[] = -{ +static struct of_device_id airport_match[] = { { - .name = "radio", + .name = "radio", }, {}, }; @@ -240,7 +239,7 @@ MODULE_DEVICE_TABLE(of, airport_match); static struct macio_driver airport_driver = { .driver = { - .name = DRIVER_NAME, + .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = airport_match, }, diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 736bbb9..f7b15b8 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -59,7 +59,7 @@ int orinoco_wiphy_register(struct wiphy *wiphy) for (i = 0; i < NUM_CHANNELS; i++) { if (priv->channel_mask & (1 << i)) { priv->channels[i].center_freq = - ieee80211_dsss_chan_to_freq(i+1); + ieee80211_dsss_chan_to_freq(i + 1); channels++; } } @@ -182,7 +182,7 @@ static int orinoco_set_channel(struct wiphy *wiphy, channel = ieee80211_freq_to_dsss_chan(chan->center_freq); if ((channel < 1) || (channel > NUM_CHANNELS) || - !(priv->channel_mask & (1 << (channel-1)))) + !(priv->channel_mask & (1 << (channel - 1)))) return -EINVAL; if (orinoco_lock(priv, &flags) != 0) @@ -191,7 +191,7 @@ static int orinoco_set_channel(struct wiphy *wiphy, priv->channel = channel; if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { /* Fast channel change - no commit if successful */ - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | HERMES_TEST_SET_CHANNEL, channel, NULL); diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index 259d758..527cf53 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c @@ -100,7 +100,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, /* Plug Data Area (PDA) */ __le16 *pda; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; const struct firmware *fw_entry; const struct orinoco_fw_header *hdr; const unsigned char *first_block; @@ -205,7 +205,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw, const unsigned char *image, const void *end, int secondary) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int ret = 0; const unsigned char *ptr; const unsigned char *first_block; @@ -322,9 +322,8 @@ symbol_dl_firmware(struct orinoco_private *priv, fw_entry->data + fw_entry->size, 1); if (!orinoco_cached_fw_get(priv, false)) release_firmware(fw_entry); - if (ret) { + if (ret) dev_err(dev, "Secondary firmware download failed\n"); - } return ret; } diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h index 89fc26d..aca63e3 100644 --- a/drivers/net/wireless/orinoco/fw.h +++ b/drivers/net/wireless/orinoco/fw.h @@ -14,7 +14,7 @@ int orinoco_download(struct orinoco_private *priv); void orinoco_cache_fw(struct orinoco_private *priv, int ap); void orinoco_uncache_fw(struct orinoco_private *priv); #else -#define orinoco_cache_fw(priv, ap) do { } while(0) +#define orinoco_cache_fw(priv, ap) do { } while (0) #define orinoco_uncache_fw(priv) do { } while (0) #endif diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index 6c6a23e..75c15bc 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c @@ -103,7 +103,7 @@ static const struct hermes_ops hermes_ops_local; Callable from any context. */ -static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0, +static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0, u16 param1, u16 param2) { int k = CMD_BUSY_TIMEOUT; @@ -132,7 +132,7 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0, */ /* For doing cmds that wipe the magic constant in SWSUPPORT0 */ -static int hermes_doicmd_wait(hermes_t *hw, u16 cmd, +static int hermes_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1, u16 parm2, struct hermes_response *resp) { @@ -185,7 +185,8 @@ out: return err; } -void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) +void hermes_struct_init(struct hermes *hw, void __iomem *address, + int reg_spacing) { hw->iobase = address; hw->reg_spacing = reg_spacing; @@ -195,7 +196,7 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) } EXPORT_SYMBOL(hermes_struct_init); -static int hermes_init(hermes_t *hw) +static int hermes_init(struct hermes *hw) { u16 reg; int err = 0; @@ -249,7 +250,7 @@ static int hermes_init(hermes_t *hw) * > 0 on error returned by the firmware * * Callable from any context, but locking is your problem. */ -static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, +static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0, struct hermes_response *resp) { int err; @@ -313,7 +314,7 @@ static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, return err; } -static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) +static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid) { int err = 0; int k; @@ -363,7 +364,7 @@ static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) * from firmware * * Callable from any context */ -static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) +static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset) { int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0; int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0; @@ -422,7 +423,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) * 0 on success * > 0 on error from firmware */ -static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, +static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len, u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -436,7 +437,7 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, goto out; /* Actually do the transfer */ - hermes_read_words(hw, dreg, buf, len/2); + hermes_read_words(hw, dreg, buf, len / 2); out: return err; @@ -450,8 +451,8 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, * 0 on success * > 0 on error from firmware */ -static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, - u16 id, u16 offset) +static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf, + int len, u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err = 0; @@ -478,8 +479,8 @@ static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, * practice. * * Callable from user or bh context. */ -static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, - u16 *length, void *buf) +static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid, + unsigned bufsize, u16 *length, void *buf) { int err = 0; int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -523,7 +524,7 @@ static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, return 0; } -static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, +static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid, u16 length, const void *value) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -553,14 +554,14 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, /*** Hermes AUX control ***/ static inline void -hermes_aux_setaddr(hermes_t *hw, u32 addr) +hermes_aux_setaddr(struct hermes *hw, u32 addr) { hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); } static inline int -hermes_aux_control(hermes_t *hw, int enabled) +hermes_aux_control(struct hermes *hw, int enabled) { int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; @@ -594,7 +595,7 @@ hermes_aux_control(hermes_t *hw, int enabled) * wl_lkm Agere fw does * Don't know about intersil */ -static int hermesi_program_init(hermes_t *hw, u32 offset) +static int hermesi_program_init(struct hermes *hw, u32 offset) { int err; @@ -643,7 +644,7 @@ static int hermesi_program_init(hermes_t *hw, u32 offset) * wl_lkm Agere fw does * Don't know about intersil */ -static int hermesi_program_end(hermes_t *hw) +static int hermesi_program_end(struct hermes *hw) { struct hermes_response resp; int rc = 0; @@ -684,7 +685,8 @@ static int hermes_program_bytes(struct hermes *hw, const char *data, } /* Read PDA from the adapter */ -static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len) +static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr, + u16 pda_len) { int ret; u16 pda_size; diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index d9f18c1..28a4244 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -28,7 +28,7 @@ * * As a module of low level hardware access routines, there is no * locking. Users of this module should ensure that they serialize - * access to the hermes_t structure, and to the hardware + * access to the hermes structure, and to the hardware */ #include <linux/if_ether.h> @@ -43,7 +43,7 @@ #define HERMES_BAP_DATALEN_MAX (4096) #define HERMES_BAP_OFFSET_MAX (4096) #define HERMES_PORTID_MAX (7) -#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX+1) +#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX + 1) #define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */ #define HERMES_PDA_RECS_MAX (200) /* a guess */ #define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */ @@ -148,7 +148,7 @@ #define HERMES_CMD_WRITEMIF (0x0031) /*--- Debugging Commands -----------------------------*/ -#define HERMES_CMD_TEST (0x0038) +#define HERMES_CMD_TEST (0x0038) /* Test command arguments */ @@ -178,8 +178,8 @@ #define HERMES_DESCRIPTOR_OFFSET 0 #define HERMES_802_11_OFFSET (14) -#define HERMES_802_3_OFFSET (14+32) -#define HERMES_802_2_OFFSET (14+32+14) +#define HERMES_802_3_OFFSET (14 + 32) +#define HERMES_802_2_OFFSET (14 + 32 + 14) #define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2) #define HERMES_RXSTAT_ERR (0x0003) @@ -406,7 +406,7 @@ struct hermes_ops { }; /* Basic control structure */ -typedef struct hermes { +struct hermes { void __iomem *iobase; int reg_spacing; #define HERMES_16BIT_REGSPACING 0 @@ -415,7 +415,7 @@ typedef struct hermes { bool eeprom_pda; const struct hermes_ops *ops; void *priv; -} hermes_t; +}; /* Register access convenience macros */ #define hermes_read_reg(hw, off) \ @@ -427,28 +427,29 @@ typedef struct hermes { hermes_write_reg((hw), HERMES_##name, (val)) /* Function prototypes */ -void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing); +void hermes_struct_init(struct hermes *hw, void __iomem *address, + int reg_spacing); /* Inline functions */ -static inline int hermes_present(hermes_t *hw) +static inline int hermes_present(struct hermes *hw) { return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC; } -static inline void hermes_set_irqmask(hermes_t *hw, u16 events) +static inline void hermes_set_irqmask(struct hermes *hw, u16 events) { hw->inten = events; hermes_write_regn(hw, INTEN, events); } -static inline int hermes_enable_port(hermes_t *hw, int port) +static inline int hermes_enable_port(struct hermes *hw, int port) { return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), 0, NULL); } -static inline int hermes_disable_port(hermes_t *hw, int port) +static inline int hermes_disable_port(struct hermes *hw, int port) { return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), 0, NULL); @@ -456,13 +457,13 @@ static inline int hermes_disable_port(hermes_t *hw, int port) /* Initiate an INQUIRE command (tallies or scan). The result will come as an * information frame in __orinoco_ev_info() */ -static inline int hermes_inquire(hermes_t *hw, u16 rid) +static inline int hermes_inquire(struct hermes *hw, u16 rid) { return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); } -#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1) -#define HERMES_RECLEN_TO_BYTES(n) (((n)-1) * 2) +#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1) +#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2) /* Note that for the next two, the count is in 16-bit words, not bytes */ static inline void hermes_read_words(struct hermes *hw, int off, @@ -498,7 +499,8 @@ static inline void hermes_clear_words(struct hermes *hw, int off, (hw->ops->write_ltv((hw), (bap), (rid), \ HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) -static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word) +static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid, + u16 *word) { __le16 rec; int err; @@ -508,7 +510,8 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word) return err; } -static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word) +static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid, + u16 word) { __le16 rec = cpu_to_le16(word); return HERMES_WRITE_RECORD(hw, bap, rid, &rec); diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index 2b2b9a1..4a10b7a 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -193,7 +193,7 @@ hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end) /* Process one Plug Data Item - find corresponding PDR and plug it */ static int -hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr, +hermes_plug_pdi(struct hermes *hw, const struct pdr *first_pdr, const struct pdi *pdi, const void *pdr_end) { const struct pdr *pdr; @@ -220,7 +220,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr, * Attempt to write every records that is in the specified pda * which also has a valid production data record for the firmware. */ -int hermes_apply_pda(hermes_t *hw, +int hermes_apply_pda(struct hermes *hw, const char *first_pdr, const void *pdr_end, const __le16 *pda, @@ -274,7 +274,7 @@ hermes_blocks_length(const char *first_block, const void *end) /*** Hermes programming ***/ /* Program the data blocks */ -int hermes_program(hermes_t *hw, const char *first_block, const void *end) +int hermes_program(struct hermes *hw, const char *first_block, const void *end) { const struct dblock *blk; u32 blkaddr; @@ -387,7 +387,7 @@ DEFINE_DEFAULT_PDR(0x0161, 256, * * For certain records, use defaults if they are not found in pda. */ -int hermes_apply_pda_with_defaults(hermes_t *hw, +int hermes_apply_pda_with_defaults(struct hermes *hw, const char *first_pdr, const void *pdr_end, const __le16 *pda, diff --git a/drivers/net/wireless/orinoco/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h index 583a5bc..b5377e2 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.h +++ b/drivers/net/wireless/orinoco/hermes_dld.h @@ -27,21 +27,21 @@ #include "hermes.h" -int hermesi_program_init(hermes_t *hw, u32 offset); -int hermesi_program_end(hermes_t *hw); -int hermes_program(hermes_t *hw, const char *first_block, const void *end); +int hermesi_program_init(struct hermes *hw, u32 offset); +int hermesi_program_end(struct hermes *hw); +int hermes_program(struct hermes *hw, const char *first_block, const void *end); -int hermes_read_pda(hermes_t *hw, +int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr, u16 pda_len, int use_eeprom); -int hermes_apply_pda(hermes_t *hw, +int hermes_apply_pda(struct hermes *hw, const char *first_pdr, const void *pdr_end, const __le16 *pda, const void *pda_end); -int hermes_apply_pda_with_defaults(hermes_t *hw, +int hermes_apply_pda_with_defaults(struct hermes *hw, const char *first_pdr, const void *pdr_end, const __le16 *pda, diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 3c7877a..c09c843 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -47,7 +47,7 @@ struct comp_id { u16 id, variant, major, minor; } __packed; -static inline fwtype_t determine_firmware_type(struct comp_id *nic_id) +static inline enum fwtype determine_firmware_type(struct comp_id *nic_id) { if (nic_id->id < 0x8000) return FIRMWARE_TYPE_AGERE; @@ -71,11 +71,11 @@ int determine_fw_capabilities(struct orinoco_private *priv, u32 *hw_ver) { struct device *dev = priv->dev; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err; struct comp_id nic_id, sta_id; unsigned int firmver; - char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2))); + char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2))); /* Get the hardware version */ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id); @@ -280,7 +280,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr) { struct device *dev = priv->dev; struct hermes_idstring nickbuf; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int len; int err; u16 reclen; @@ -458,7 +458,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) { struct net_device *dev = priv->ndev; struct wireless_dev *wdev = netdev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err; struct hermes_idstring idbuf; @@ -529,7 +529,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */ err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, - HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2), &idbuf); if (err) { printk(KERN_ERR "%s: Error %d setting OWNSSID\n", @@ -537,7 +537,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) return err; } err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, - HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2), &idbuf); if (err) { printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", @@ -549,7 +549,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) idbuf.len = cpu_to_le16(strlen(priv->nick)); memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val)); err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, - HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), + HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2), &idbuf); if (err) { printk(KERN_ERR "%s: Error %d setting nickname\n", @@ -689,7 +689,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv) /* Get tsc from the firmware */ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; u8 tsc_arr[4][ORINOCO_SEQ_LEN]; @@ -706,7 +706,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc) int __orinoco_hw_set_bitrate(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int ratemode = priv->bitratemode; int err = 0; @@ -737,7 +737,7 @@ int __orinoco_hw_set_bitrate(struct orinoco_private *priv) int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int i; int err = 0; u16 val; @@ -786,7 +786,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv) { int roaming_flag; int err = 0; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; switch (priv->firmware_type) { case FIRMWARE_TYPE_AGERE: @@ -818,7 +818,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv) * which is needed for 802.1x implementations. */ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; int i; @@ -902,7 +902,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv) int __orinoco_hw_setup_enc(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; int master_wep_flag; int auth_flag; @@ -999,7 +999,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, u8 rx_mic[MIC_KEYLEN]; u8 tsc[ORINOCO_SEQ_LEN]; } __packed buf; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int ret; int err; int k; @@ -1052,7 +1052,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err; err = hermes_write_wordrec(hw, USER_BAP, @@ -1068,7 +1068,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, struct net_device *dev, int mc_count, int promisc) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; if (promisc != priv->promiscuous) { @@ -1111,9 +1111,9 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, /* Return : < 0 -> error code ; >= 0 -> length */ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]) + char buf[IW_ESSID_MAX_SIZE + 1]) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; struct hermes_idstring essidbuf; char *p = (char *)(&essidbuf.val); @@ -1166,7 +1166,7 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, int orinoco_hw_get_freq(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; u16 channel; int freq = 0; @@ -1206,7 +1206,7 @@ int orinoco_hw_get_freq(struct orinoco_private *priv) int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates, s32 *rates, int max) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; struct hermes_idstring list; unsigned char *p = (unsigned char *)&list.val; int err = 0; @@ -1238,7 +1238,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv, const struct cfg80211_ssid *ssid) { struct net_device *dev = priv->ndev; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; unsigned long flags; int err = 0; @@ -1323,7 +1323,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv, int orinoco_hw_disassociate(struct orinoco_private *priv, u8 *addr, u16 reason_code) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err; struct { @@ -1346,7 +1346,7 @@ int orinoco_hw_disassociate(struct orinoco_private *priv, int orinoco_hw_get_current_bssid(struct orinoco_private *priv, u8 *addr) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err; err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h index 97af71e..8f6831f 100644 --- a/drivers/net/wireless/orinoco/hw.h +++ b/drivers/net/wireless/orinoco/hw.h @@ -45,7 +45,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, struct net_device *dev, int mc_count, int promisc); int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]); + char buf[IW_ESSID_MAX_SIZE + 1]); int orinoco_hw_get_freq(struct orinoco_private *priv); int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates, s32 *rates, int max); diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index b0f233f..ef7efe8 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -4,7 +4,7 @@ * adaptors, with Lucent/Agere, Intersil or Symbol firmware. * * Current maintainers (as of 29 September 2003) are: - * Pavel Roskin <proski AT gnu.org> + * Pavel Roskin <proski AT gnu.org> * and David Gibson <hermes AT gibson.dropbear.id.au> * * (C) Copyright David Gibson, IBM Corporation 2001-2003. @@ -146,10 +146,10 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; #define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD) #define MAX_IRQLOOPS_PER_IRQ 10 -#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of - * how many events the - * device could - * legitimately generate */ +#define MAX_IRQLOOPS_PER_JIFFY (20000 / HZ) /* Based on a guestimate of + * how many events the + * device could + * legitimately generate */ #define DUMMY_FID 0xFFFF @@ -157,7 +157,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; HERMES_MAX_MULTICAST : 0)*/ #define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST) -#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \ +#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \ | HERMES_EV_TX | HERMES_EV_TXEXC \ | HERMES_EV_WTERR | HERMES_EV_INFO \ | HERMES_EV_INFDROP) @@ -437,12 +437,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; u16 txfid = priv->txfid; int tx_control; unsigned long flags; - u8 mic_buf[MICHAEL_MIC_LEN+1]; + u8 mic_buf[MICHAEL_MIC_LEN + 1]; if (!netif_running(dev)) { printk(KERN_ERR "%s: Tx on stopped device!\n", @@ -579,7 +579,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } -static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_alloc(struct net_device *dev, struct hermes *hw) { struct orinoco_private *priv = ndev_priv(dev); u16 fid = hermes_read_regn(hw, ALLOCFID); @@ -594,7 +594,7 @@ static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) hermes_write_regn(hw, ALLOCFID, DUMMY_FID); } -static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_tx(struct net_device *dev, struct hermes *hw) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -606,7 +606,7 @@ static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); } -static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_txexc(struct net_device *dev, struct hermes *hw) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -753,7 +753,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, struct sk_buff *skb; struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; len = le16_to_cpu(desc->data_len); @@ -840,7 +840,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, stats->rx_dropped++; } -void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -918,7 +918,7 @@ void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 32bit boundary, plus 1 byte so we can read in odd length packets from the card, which has an IO granularity of 16 bits */ - skb = dev_alloc_skb(length+ETH_HLEN+2+1); + skb = dev_alloc_skb(length + ETH_HLEN + 2 + 1); if (!skb) { printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", dev->name); @@ -1402,7 +1402,7 @@ static void orinoco_process_scan_results(struct work_struct *work) spin_unlock_irqrestore(&priv->scan_lock, flags); } -void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_info(struct net_device *dev, struct hermes *hw) { struct orinoco_private *priv = ndev_priv(dev); u16 infofid; @@ -1620,7 +1620,7 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) } EXPORT_SYMBOL(__orinoco_ev_info); -static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_infdrop(struct net_device *dev, struct hermes *hw) { if (net_ratelimit()) printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name); @@ -1831,7 +1831,7 @@ static int __orinoco_commit(struct orinoco_private *priv) int orinoco_commit(struct orinoco_private *priv) { struct net_device *dev = priv->ndev; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err; if (priv->broken_disableport) { @@ -1874,12 +1874,12 @@ int orinoco_commit(struct orinoco_private *priv) /* Interrupt handler */ /********************************************************************/ -static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_tick(struct net_device *dev, struct hermes *hw) { printk(KERN_DEBUG "%s: TICK\n", dev->name); } -static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_wterr(struct net_device *dev, struct hermes *hw) { /* This seems to happen a fair bit under load, but ignoring it seems to work fine...*/ @@ -1891,7 +1891,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id) { struct orinoco_private *priv = dev_id; struct net_device *dev = priv->ndev; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int count = MAX_IRQLOOPS_PER_IRQ; u16 evstat, events; /* These are used to detect a runaway interrupt situation. @@ -2017,8 +2017,8 @@ static void orinoco_unregister_pm_notifier(struct orinoco_private *priv) unregister_pm_notifier(&priv->pm_notifier); } #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ -#define orinoco_register_pm_notifier(priv) do { } while(0) -#define orinoco_unregister_pm_notifier(priv) do { } while(0) +#define orinoco_register_pm_notifier(priv) do { } while (0) +#define orinoco_unregister_pm_notifier(priv) do { } while (0) #endif /********************************************************************/ @@ -2029,7 +2029,7 @@ int orinoco_init(struct orinoco_private *priv) { struct device *dev = priv->dev; struct wiphy *wiphy = priv_to_wiphy(priv); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; /* No need to lock, the hw_unavailable flag is already set in diff --git a/drivers/net/wireless/orinoco/mic.c b/drivers/net/wireless/orinoco/mic.c index c03e7f5..fce4a84 100644 --- a/drivers/net/wireless/orinoco/mic.c +++ b/drivers/net/wireless/orinoco/mic.c @@ -59,10 +59,10 @@ int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, /* Copy header into buffer. We need the padding on the end zeroed */ memcpy(&hdr[0], da, ETH_ALEN); memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN); - hdr[ETH_ALEN*2] = priority; - hdr[ETH_ALEN*2+1] = 0; - hdr[ETH_ALEN*2+2] = 0; - hdr[ETH_ALEN*2+3] = 0; + hdr[ETH_ALEN * 2] = priority; + hdr[ETH_ALEN * 2 + 1] = 0; + hdr[ETH_ALEN * 2 + 2] = 0; + hdr[ETH_ALEN * 2 + 3] = 0; /* Use scatter gather to MIC header and data in one go */ sg_init_table(sg, 2); diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 255710e..3bb936b 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -49,11 +49,11 @@ enum orinoco_alg { ORINOCO_ALG_TKIP }; -typedef enum { +enum fwtype { FIRMWARE_TYPE_AGERE, FIRMWARE_TYPE_INTERSIL, FIRMWARE_TYPE_SYMBOL -} fwtype_t; +}; struct firmware; @@ -88,11 +88,11 @@ struct orinoco_private { struct iw_statistics wstats; /* Hardware control variables */ - hermes_t hw; + struct hermes hw; u16 txfid; /* Capabilities of the hardware/firmware */ - fwtype_t firmware_type; + enum fwtype firmware_type; int ibss_port; int nicbuf_size; u16 channel_mask; @@ -122,8 +122,8 @@ struct orinoco_private { struct key_params keys[ORINOCO_MAX_KEYS]; int bitratemode; - char nick[IW_ESSID_MAX_SIZE+1]; - char desired_essid[IW_ESSID_MAX_SIZE+1]; + char nick[IW_ESSID_MAX_SIZE + 1]; + char desired_essid[IW_ESSID_MAX_SIZE + 1]; char desired_bssid[ETH_ALEN]; int bssid_fixed; u16 frag_thresh, mwo_robust; @@ -197,8 +197,8 @@ extern int orinoco_up(struct orinoco_private *priv); extern void orinoco_down(struct orinoco_private *priv); extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); -extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); -extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); +extern void __orinoco_ev_info(struct net_device *dev, struct hermes *hw); +extern void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw); int orinoco_process_xmit_skb(struct sk_buff *skb, struct net_device *dev, diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 88e3c0e..3f7fc4a 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -65,7 +65,7 @@ static void orinoco_cs_release(struct pcmcia_device *link); static void orinoco_cs_detach(struct pcmcia_device *p_dev); /********************************************************************/ -/* Device methods */ +/* Device methods */ /********************************************************************/ static int @@ -89,7 +89,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) } /********************************************************************/ -/* PCMCIA stuff */ +/* PCMCIA stuff */ /********************************************************************/ static int @@ -134,7 +134,7 @@ static int orinoco_cs_config(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int ret; void __iomem *mem; diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index bc3ea0b..326396b 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c @@ -296,8 +296,7 @@ static struct pci_driver orinoco_nortel_driver = { static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)"; MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>"); -MODULE_DESCRIPTION - ("Driver for wireless LAN cards using the Nortel PCI bridge"); +MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge"); MODULE_LICENSE("Dual MPL/GPL"); static int __init orinoco_nortel_init(void) diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index 468197f..6058c66 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c @@ -6,7 +6,7 @@ * hermes registers, as well as the COR register. * * Current maintainers are: - * Pavel Roskin <proski AT gnu.org> + * Pavel Roskin <proski AT gnu.org> * and David Gibson <hermes AT gibson.dropbear.id.au> * * Some of this code is borrowed from orinoco_plx.c @@ -81,7 +81,7 @@ */ static int orinoco_pci_cor_reset(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; unsigned long timeout; u16 reg; diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index 9358f4d..2bac824 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c @@ -4,7 +4,7 @@ * but are connected to the PCI bus by a PLX9052. * * Current maintainers are: - * Pavel Roskin <proski AT gnu.org> + * Pavel Roskin <proski AT gnu.org> * and David Gibson <hermes AT gibson.dropbear.id.au> * * (C) Copyright David Gibson, IBM Corp. 2001-2003. @@ -102,14 +102,14 @@ #define PLX_RESET_TIME (500) /* milliseconds */ #define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ -#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ +#define PLX_INTCSR_INTEN (1 << 6) /* Interrupt Enable bit */ /* * Do a soft reset of the card using the Configuration Option Register */ static int orinoco_plx_cor_reset(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; struct orinoco_pci_card *card = priv->card; unsigned long timeout; u16 reg; diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 784605f..93159d6 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c @@ -59,7 +59,7 @@ */ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) { - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; struct orinoco_pci_card *card = priv->card; unsigned long timeout; u16 reg; diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index b9aedf1..811e87f 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -199,7 +199,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw"); #define EZUSB_FRAME_DATA 1 #define EZUSB_FRAME_CONTROL 2 -#define DEF_TIMEOUT (3*HZ) +#define DEF_TIMEOUT (3 * HZ) #define BULK_BUF_SIZE 2048 @@ -959,7 +959,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, return retval; } -static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid, +static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid, u16 length, const void *data) { struct ezusb_priv *upriv = hw->priv; @@ -989,7 +989,7 @@ static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid, NULL, 0, NULL); } -static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid, +static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, unsigned bufsize, u16 *length, void *buf) { struct ezusb_priv *upriv = hw->priv; @@ -1006,7 +1006,7 @@ static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid, buf, bufsize, length); } -static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1, +static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1, u16 parm2, struct hermes_response *resp) { struct ezusb_priv *upriv = hw->priv; @@ -1028,7 +1028,7 @@ static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1, EZUSB_FRAME_CONTROL, NULL, 0, NULL); } -static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, +static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0, struct hermes_response *resp) { struct ezusb_priv *upriv = hw->priv; @@ -1196,7 +1196,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; struct ezusb_priv *upriv = priv->card; - u8 mic[MICHAEL_MIC_LEN+1]; + u8 mic[MICHAEL_MIC_LEN + 1]; int err = 0; int tx_control; unsigned long flags; @@ -1356,7 +1356,7 @@ static int ezusb_hard_reset(struct orinoco_private *priv) } -static int ezusb_init(hermes_t *hw) +static int ezusb_init(struct hermes *hw) { struct ezusb_priv *upriv = hw->priv; int retval; @@ -1438,7 +1438,7 @@ static void ezusb_bulk_in_callback(struct urb *urb) } else if (upriv->dev) { struct net_device *dev = upriv->dev; struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; if (hermes_rid == EZUSB_RID_RX) { __orinoco_ev_rx(dev, hw); @@ -1575,7 +1575,7 @@ static int ezusb_probe(struct usb_interface *interface, { struct usb_device *udev = interface_to_usbdev(interface); struct orinoco_private *priv; - hermes_t *hw; + struct hermes *hw; struct ezusb_priv *upriv = NULL; struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *ep; @@ -1757,7 +1757,7 @@ static struct usb_driver orinoco_driver = { /* Can't be declared "const" or the whole __initdata section will * become const */ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Manuel Estrada Sainz)"; + " (Manuel Estrada Sainz)"; static int __init ezusb_module_init(void) { @@ -1787,6 +1787,5 @@ module_init(ezusb_module_init); module_exit(ezusb_module_exit); MODULE_AUTHOR("Manuel Estrada Sainz"); -MODULE_DESCRIPTION - ("Driver for Orinoco wireless LAN cards using EZUSB bridge"); +MODULE_DESCRIPTION("Driver for Orinoco wireless LAN cards using EZUSB bridge"); MODULE_LICENSE("Dual MPL/GPL"); diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 81f3673..6e28ee4 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -11,9 +11,9 @@ * * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org> * Portions based on orinoco_cs.c: - * Copyright (C) David Gibson, Linuxcare Australia + * Copyright (C) David Gibson, Linuxcare Australia * Portions based on Spectrum24tDnld.c from original spectrum24 driver: - * Copyright (C) Symbol Technologies. + * Copyright (C) Symbol Technologies. * * See copyright notice in file main.c. */ @@ -125,7 +125,7 @@ failed: } /********************************************************************/ -/* Device methods */ +/* Device methods */ /********************************************************************/ static int @@ -150,7 +150,7 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle) } /********************************************************************/ -/* PCMCIA stuff */ +/* PCMCIA stuff */ /********************************************************************/ static int @@ -197,7 +197,7 @@ static int spectrum_cs_config(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int ret; void __iomem *mem; diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index e793679..bbb9beb 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -87,7 +87,7 @@ nomem: static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; struct iw_statistics *wstats = &priv->wstats; int err; unsigned long flags; @@ -448,7 +448,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, } if ((chan < 1) || (chan > NUM_CHANNELS) || - !(priv->channel_mask & (1 << (chan-1)))) + !(priv->channel_mask & (1 << (chan - 1)))) return -EINVAL; if (orinoco_lock(priv, &flags) != 0) @@ -457,7 +457,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, priv->channel = chan; if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { /* Fast channel change - no commit if successful */ - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | HERMES_TEST_SET_CHANNEL, chan, NULL); @@ -492,7 +492,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev, char *extra) { struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; u16 val; int err; unsigned long flags; @@ -668,7 +668,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev, char *extra) { struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int err = 0; u16 enable, period, timeout, mcast; unsigned long flags; @@ -873,7 +873,7 @@ static int orinoco_ioctl_set_auth(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; struct iw_param *param = &wrqu->param; unsigned long flags; int ret = -EINPROGRESS; @@ -1269,7 +1269,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev, char *extra) { struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; + struct hermes *hw = &priv->hw; int rid = data->flags; u16 length; int err; diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index bc13533..0b598db 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/ip.h> #include "wifi.h" #include "rc.h" @@ -397,8 +399,8 @@ void rtl_init_rfkill(struct ieee80211_hw *hw) radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); if (valid) { - printk(KERN_INFO "rtlwifi: wireless switch is %s\n", - rtlpriv->rfkill.rfkill_state ? "on" : "off"); + pr_info("wireless switch is %s\n", + rtlpriv->rfkill.rfkill_state ? "on" : "off"); rtlpriv->rfkill.rfkill_state = radio_state; @@ -756,18 +758,17 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) return false; RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - ("%s ACT_ADDBAREQ From :" MAC_FMT "\n", - is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2))); + ("%s ACT_ADDBAREQ From :%pM\n", + is_tx ? "Tx" : "Rx", hdr->addr2)); break; case ACT_ADDBARSP: RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - ("%s ACT_ADDBARSP From :" MAC_FMT "\n", - is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2))); + ("%s ACT_ADDBARSP From :%pM\n", + is_tx ? "Tx" : "Rx", hdr->addr2)); break; case ACT_DELBA: RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - ("ACT_ADDBADEL From :" MAC_FMT "\n", - MAC_ARG(hdr->addr2))); + ("ACT_ADDBADEL From :%pM\n", hdr->addr2)); break; } break; @@ -1402,8 +1403,7 @@ MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); static int __init rtl_core_module_init(void) { if (rtl_rate_control_register()) - printk(KERN_ERR "rtlwifi: Unable to register rtl_rc," - "use default RC !!\n"); + pr_err("Unable to register rtl_rc, use default RC !!\n"); return 0; } diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c index 7295af0..7babb6a 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/rtlwifi/cam.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "wifi.h" #include "cam.h" @@ -131,9 +133,9 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, " - "ulUseDK=%x MacAddr" MAC_FMT "\n", + "ulUseDK=%x MacAddr %pM\n", ul_entry_idx, ul_key_id, ul_enc_alg, - ul_default_key, MAC_ARG(mac_addr))); + ul_default_key, mac_addr)); if (ul_key_id == TOTAL_CAM_ENTRY) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, @@ -347,7 +349,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) /* Remove from HW Security CAM */ memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); - printk(KERN_INFO "&&&&&&&&&del entry %d\n", i); + pr_info("&&&&&&&&&del entry %d\n", i); } } return; diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 03ce696..1bdc1aa 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -456,7 +456,7 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw, sta_entry->wireless_mode = WIRELESS_MODE_G; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); + ("Add sta addr is %pM\n", sta->addr)); rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); } return 0; @@ -469,7 +469,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, struct rtl_sta_info *sta_entry; if (sta) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); + ("Remove sta addr is %pM\n", sta->addr)); sta_entry = (struct rtl_sta_info *) sta->drv_priv; sta_entry->wireless_mode = 0; sta_entry->ratr_index = 0; @@ -678,7 +678,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, (u8 *) bss_conf->bssid); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); + ("%pM\n", bss_conf->bssid)); mac->vendor = PEER_UNKNOWN; memcpy(mac->bssid, bss_conf->bssid, 6); diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h index e4aa868..160dd06 100644 --- a/drivers/net/wireless/rtlwifi/debug.h +++ b/drivers/net/wireless/rtlwifi/debug.h @@ -204,10 +204,5 @@ enum dbgp_flag_e { } \ } while (0); -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) \ - ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2],\ - ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5] - void rtl_dbgp_flag_init(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index f9f2370..49a064b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/firmware.h> #include "../wifi.h" #include "../pci.h" @@ -224,8 +226,7 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) u32 fwsize; enum version_8192c version = rtlhal->version; - printk(KERN_INFO "rtl8192c: Loading firmware file %s\n", - rtlpriv->cfg->fw_name); + pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); if (!rtlhal->pfirmware) return 1; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 9e2a9e3..a3deaef 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -1592,7 +1592,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) } RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); + ("%pM\n", rtlefuse->dev_addr)); _rtl92ce_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 2b34764..814c05d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "../wifi.h" #include "../efuse.h" #include "../base.h" @@ -337,7 +339,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents) rtlefuse->board_type = boardType; if (IS_HIGHT_PA(rtlefuse->board_type)) rtlefuse->external_pa = 1; - printk(KERN_INFO "rtl8192cu: Board Type %x\n", rtlefuse->board_type); + pr_info("Board Type %x\n", rtlefuse->board_type); #ifdef CONFIG_ANTENNA_DIVERSITY /* Antenna Diversity setting. */ @@ -346,8 +348,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents) else rtl_efuse->antenna_cfg = registry_par->antdiv_cfg; /* 0:OFF, */ - printk(KERN_INFO "rtl8192cu: Antenna Config %x\n", - rtl_efuse->antenna_cfg); + pr_info("Antenna Config %x\n", rtl_efuse->antenna_cfg); #endif } @@ -384,71 +385,57 @@ static void _update_bt_param(_adapter *padapter) pbtpriv->bBTNonTrafficModeSet = _FALSE; pbtpriv->CurrentState = 0; pbtpriv->PreviousState = 0; - printk(KERN_INFO "rtl8192cu: BT Coexistance = %s\n", - (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable"); + pr_info("BT Coexistance = %s\n", + (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable"); if (pbtpriv->BT_Coexist) { if (pbtpriv->BT_Ant_Num == Ant_x2) - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "Ant_Num = Antx2\n"); + pr_info("BlueTooth BT_Ant_Num = Antx2\n"); else if (pbtpriv->BT_Ant_Num == Ant_x1) - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "Ant_Num = Antx1\n"); + pr_info("BlueTooth BT_Ant_Num = Antx1\n"); switch (pbtpriv->BT_CoexistType) { case BT_2Wire: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = BT_2Wire\n"); + pr_info("BlueTooth BT_CoexistType = BT_2Wire\n"); break; case BT_ISSC_3Wire: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = BT_ISSC_3Wire\n"); + pr_info("BlueTooth BT_CoexistType = BT_ISSC_3Wire\n"); break; case BT_Accel: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = BT_Accel\n"); + pr_info("BlueTooth BT_CoexistType = BT_Accel\n"); break; case BT_CSR_BC4: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = BT_CSR_BC4\n"); + pr_info("BlueTooth BT_CoexistType = BT_CSR_BC4\n"); break; case BT_CSR_BC8: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = BT_CSR_BC8\n"); + pr_info("BlueTooth BT_CoexistType = BT_CSR_BC8\n"); break; case BT_RTL8756: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = BT_RTL8756\n"); + pr_info("BlueTooth BT_CoexistType = BT_RTL8756\n"); break; default: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_" - "CoexistType = Unknown\n"); + pr_info("BlueTooth BT_CoexistType = Unknown\n"); break; } - printk(KERN_INFO "rtl8192cu: BlueTooth BT_Ant_isolation = %d\n", - pbtpriv->BT_Ant_isolation); + pr_info("BlueTooth BT_Ant_isolation = %d\n", + pbtpriv->BT_Ant_isolation); switch (pbtpriv->BT_Service) { case BT_OtherAction: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = " - "BT_OtherAction\n"); + pr_info("BlueTooth BT_Service = BT_OtherAction\n"); break; case BT_SCO: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = " - "BT_SCO\n"); + pr_info("BlueTooth BT_Service = BT_SCO\n"); break; case BT_Busy: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = " - "BT_Busy\n"); + pr_info("BlueTooth BT_Service = BT_Busy\n"); break; case BT_OtherBusy: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = " - "BT_OtherBusy\n"); + pr_info("BlueTooth BT_Service = BT_OtherBusy\n"); break; default: - printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = " - "BT_Idle\n"); + pr_info("BlueTooth BT_Service = BT_Idle\n"); break; } - printk(KERN_INFO "rtl8192cu: BT_RadioSharedType = 0x%x\n", - pbtpriv->BT_RadioSharedType); + pr_info("BT_RadioSharedType = 0x%x\n", + pbtpriv->BT_RadioSharedType); } } @@ -526,7 +513,7 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw) usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; } - printk(KERN_INFO "rtl8192cu: MAC address: %pM\n", rtlefuse->dev_addr); + pr_info("MAC address: %pM\n", rtlefuse->dev_addr); _rtl92cu_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, hwinfo); rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; @@ -665,7 +652,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) rtl_write_word(rtlpriv, REG_APS_FSMCO, value16); do { if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) { - printk(KERN_INFO "rtl8192cu: MAC auto ON okay!\n"); + pr_info("MAC auto ON okay!\n"); break; } if (pollingCount++ > 100) { @@ -819,7 +806,7 @@ static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw, } _rtl92c_init_chipN_reg_priority(hw, value, value, value, value, value, value); - printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel); + pr_info("Tx queue select: 0x%02x\n", queue_sel); } static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw, @@ -863,7 +850,7 @@ static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw, hiQ = valueHi; } _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); - printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel); + pr_info("Tx queue select: 0x%02x\n", queue_sel); } static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index a90c09b..194fc69 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -26,6 +26,9 @@ * Larry Finger <Larry.Finger@lwfinger.net> * ****************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include "../wifi.h" @@ -213,14 +216,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) for (i = 0; i < (boundary - 1); i++) { rst = rtl92c_llt_write(hw, i , i + 1); if (true != rst) { - printk(KERN_ERR "===> %s #1 fail\n", __func__); + pr_err("===> %s #1 fail\n", __func__); return rst; } } /* end of list */ rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF); if (true != rst) { - printk(KERN_ERR "===> %s #2 fail\n", __func__); + pr_err("===> %s #2 fail\n", __func__); return rst; } /* Make the other pages as ring buffer @@ -231,14 +234,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) { rst = rtl92c_llt_write(hw, i, (i + 1)); if (true != rst) { - printk(KERN_ERR "===> %s #3 fail\n", __func__); + pr_err("===> %s #3 fail\n", __func__); return rst; } } /* Let last entry point to the start entry of ring buffer */ rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary); if (true != rst) { - printk(KERN_ERR "===> %s #4 fail\n", __func__); + pr_err("===> %s #4 fail\n", __func__); return rst; } return rst; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 5a65bea..0073cf1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c @@ -1829,7 +1829,7 @@ static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, rtlefuse->dev_addr); RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); + ("%pM\n", rtlefuse->dev_addr)); _rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo); /* Read Channel Plan */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 0883774..351765d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/vmalloc.h> #include "../wifi.h" @@ -170,10 +172,8 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) } if (!header_print) { - printk(KERN_INFO "rtl8192de: Driver for Realtek RTL8192DE" - " WLAN interface"); - printk(KERN_INFO "rtl8192de: Loading firmware file %s\n", - rtlpriv->cfg->fw_name); + pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); + pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); header_print++; } /* request fw */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index b1d0213..d59f66c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "../wifi.h" #include "../efuse.h" #include "../base.h" @@ -465,8 +467,7 @@ static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data) if ((tmpvalue & BIT(6))) break; - printk(KERN_ERR "wait for BIT(6) return value %x\n", - tmpvalue); + pr_err("wait for BIT(6) return value %x\n", tmpvalue); if (waitcount == 0) break; @@ -1255,8 +1256,7 @@ static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) if ((tmp & BIT(6))) break; - printk(KERN_ERR "wait for BIT(6) return value %x\n", - tmp); + pr_err("wait for BIT(6) return value %x\n", tmp); if (waitcnt == 0) break; @@ -1315,7 +1315,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) if (u1btmp & BIT(7)) { u1btmp &= ~(BIT(6) | BIT(7)); if (!_rtl92s_set_sysclk(hw, u1btmp)) { - printk(KERN_ERR "Switch ctrl path fail\n"); + pr_err("Switch ctrl path fail\n"); return; } } @@ -1682,7 +1682,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); + ("%pM\n", rtlefuse->dev_addr)); /* Get Tx Power Level by Channel */ /* Read Tx power of Channel 1 ~ 14 from EEPROM. */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 81a5aa4..f27171a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "../wifi.h" #include "../pci.h" #include "../ps.h" @@ -1016,8 +1018,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB); if (rtstatus != true) { - printk(KERN_ERR "_rtl92s_phy_bb_config_parafile(): " - "AGC Table Fail\n"); + pr_err("%s(): AGC Table Fail\n", __func__); goto phy_BB8190_Config_ParaFile_Fail; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c index c6e3a4c..0ad50fe 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "../wifi.h" #include "reg.h" #include "def.h" @@ -507,7 +509,7 @@ bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) } if (rtstatus != true) { - printk(KERN_ERR "Radio[%d] Fail!!", rfpath); + pr_err("Radio[%d] Fail!!\n", rfpath); goto fail; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 1c6cb1d..3876078 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/vmalloc.h> #include "../wifi.h" @@ -183,8 +185,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) return 1; } - printk(KERN_INFO "rtl8192se: Driver for Realtek RTL8192SE/RTL8191SE\n" - " Loading firmware %s\n", rtlpriv->cfg->fw_name); + pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" + "Loading firmware %s\n", rtlpriv->cfg->fw_name); /* request fw */ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, rtlpriv->io.dev); diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index a9367eb..8b1cef0 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -24,6 +24,9 @@ * Hsinchu 300, Taiwan. * *****************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/usb.h> #include "core.h" #include "wifi.h" @@ -104,9 +107,8 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, pdata, len, 0); /* max. timeout */ if (status < 0) - printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! " - "status:0x%x value=0x%x\n", value, status, - *(u32 *)pdata); + pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n", + value, status, *(u32 *)pdata); return status; } @@ -316,7 +318,7 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw) rtlusb->usb_rx_segregate_hdl = rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl; - printk(KERN_INFO "rtl8192cu: rx_max_size %d, rx_urb_num %d, in_ep %d\n", + pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); init_usb_anchor(&rtlusb->rx_submitted); return 0; @@ -580,7 +582,7 @@ static void _rtl_rx_completed(struct urb *_urb) } else{ /* TO DO */ _rtl_rx_pre_process(hw, skb); - printk(KERN_ERR "rtlwifi: rx agg not supported\n"); + pr_err("rx agg not supported\n"); } goto resubmit; } diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 57b7b64..6ec6e09 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1266,7 +1266,10 @@ u32 ssb_dma_translation(struct ssb_device *dev) case SSB_BUSTYPE_SSB: return 0; case SSB_BUSTYPE_PCI: - return SSB_PCI_DMA; + if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) + return SSB_PCIE_DMA_H32; + else + return SSB_PCI_DMA; default: __ssb_dma_not_implemented(dev); } diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 3895aeb..8c96654 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -25,6 +25,11 @@ struct bcma_chipinfo { u8 pkg; }; +enum bcma_clkmode { + BCMA_CLKMODE_FAST, + BCMA_CLKMODE_DYNAMIC, +}; + struct bcma_host_ops { u8 (*read8)(struct bcma_device *core, u16 offset); u16 (*read16)(struct bcma_device *core, u16 offset); @@ -243,8 +248,24 @@ void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value) core->bus->ops->awrite32(core, offset, value); } +#define bcma_mask32(cc, offset, mask) \ + bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask)) +#define bcma_set32(cc, offset, set) \ + bcma_write32(cc, offset, bcma_read32(cc, offset) | (set)) +#define bcma_maskset32(cc, offset, mask, set) \ + bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set)) + extern bool bcma_core_is_enabled(struct bcma_device *core); extern void bcma_core_disable(struct bcma_device *core, u32 flags); extern int bcma_core_enable(struct bcma_device *core, u32 flags); +extern void bcma_core_set_clockmode(struct bcma_device *core, + enum bcma_clkmode clkmode); +extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, + bool on); +#define BCMA_DMA_TRANSLATION_MASK 0xC0000000 +#define BCMA_DMA_TRANSLATION_NONE 0x00000000 +#define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */ +#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */ +extern u32 bcma_core_dma_translation(struct bcma_device *core); #endif /* LINUX_BCMA_H_ */ diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 9c5b69f..a0f6846 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -179,15 +179,7 @@ #define BCMA_CC_PROG_WAITCNT 0x0124 #define BCMA_CC_FLASH_CFG 0x0128 #define BCMA_CC_FLASH_WAITCNT 0x012C -#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */ -#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ -#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ -#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ -#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ -#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ -#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ -#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */ -#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */ +/* 0x1E0 is defined as shared BCMA_CLKCTLST */ #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ #define BCMA_CC_UART0_DATA 0x0300 #define BCMA_CC_UART0_IMR 0x0304 @@ -244,7 +236,8 @@ #define BCMA_CC_REGCTL_DATA 0x065C #define BCMA_CC_PLLCTL_ADDR 0x0660 #define BCMA_CC_PLLCTL_DATA 0x0664 -#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */ +#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ +#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index f82d88a..9faae2a 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h @@ -1,13 +1,38 @@ #ifndef LINUX_BCMA_REGS_H_ #define LINUX_BCMA_REGS_H_ +/* Some single registers are shared between many cores */ +/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */ +#define BCMA_CLKCTLST 0x01E0 /* Clock control and status */ +#define BCMA_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ +#define BCMA_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ +#define BCMA_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ +#define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ +#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ +#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ +#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */ +#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */ +#define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */ +#define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */ +#define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */ +#define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */ +/* Is there any BCM4328 on BCMA bus? */ +#define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */ +#define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */ + /* Agent registers (common for every core) */ -#define BCMA_IOCTL 0x0408 +#define BCMA_IOCTL 0x0408 /* IO control */ #define BCMA_IOCTL_CLK 0x0001 #define BCMA_IOCTL_FGC 0x0002 #define BCMA_IOCTL_CORE_BITS 0x3FFC #define BCMA_IOCTL_PME_EN 0x4000 #define BCMA_IOCTL_BIST_EN 0x8000 +#define BCMA_IOST 0x0500 /* IO status */ +#define BCMA_IOST_CORE_BITS 0x0FFF +#define BCMA_IOST_DMA64 0x1000 +#define BCMA_IOST_GATED_CLK 0x2000 +#define BCMA_IOST_BIST_ERROR 0x4000 +#define BCMA_IOST_BIST_DONE 0x8000 #define BCMA_RESET_CTL 0x0800 #define BCMA_RESET_CTL_RESET 0x0001 diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a26108e..54c8789 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1453,6 +1453,43 @@ enum ieee80211_sa_query_action { #define WLAN_PMKID_LEN 16 +/* + * WMM/802.11e Tspec Element + */ +#define IEEE80211_WMM_IE_TSPEC_TID_MASK 0x0F +#define IEEE80211_WMM_IE_TSPEC_TID_SHIFT 1 + +enum ieee80211_tspec_status_code { + IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED = 0, + IEEE80211_TSPEC_STATUS_ADDTS_INVAL_PARAMS = 0x1, +}; + +struct ieee80211_tspec_ie { + u8 element_id; + u8 len; + u8 oui[3]; + u8 oui_type; + u8 oui_subtype; + u8 version; + __le16 tsinfo; + u8 tsinfo_resvd; + __le16 nominal_msdu; + __le16 max_msdu; + __le32 min_service_int; + __le32 max_service_int; + __le32 inactivity_int; + __le32 suspension_int; + __le32 service_start_time; + __le32 min_data_rate; + __le32 mean_data_rate; + __le32 peak_data_rate; + __le32 max_burst_size; + __le32 delay_bound; + __le32 min_phy_rate; + __le16 sba; + __le16 medium_time; +} __packed; + /** * ieee80211_get_qos_ctl - get pointer to qos control bytes * @hdr: the frame diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 8cb025a..e4da76c 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -756,8 +756,12 @@ enum nl80211_commands { * * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can + * scan with a single scheduled scan request, a wiphy attribute. * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements * that can be added to a scan request + * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information + * elements that can be added to a scheduled scan request * * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive @@ -989,8 +993,8 @@ enum nl80211_commands { * driving the peer link management state machine. * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. * - * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities, - * the supported WoWLAN triggers + * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy + * capabilities, the supported WoWLAN triggers * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to * indicate which WoW triggers should be enabled. This is also * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN @@ -1010,6 +1014,11 @@ enum nl80211_commands { * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data. * + * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan, + * nested array attribute containing an entry for each band, with the entry + * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but + * without the length restriction (at most %NL80211_MAX_SUPP_RATES). + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1210,6 +1219,11 @@ enum nl80211_attrs { NL80211_ATTR_REKEY_DATA, + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + + NL80211_ATTR_SCAN_SUPP_RATES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2255,6 +2269,16 @@ struct nl80211_wowlan_pattern_support { * * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute * carrying a &struct nl80211_wowlan_pattern_support. + * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be + * used when setting, used only to indicate that GTK rekeying is supported + * by the device (flag) + * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if + * done by the device) (flag) + * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request + * packet (flag) + * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) + * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released + * (on devices that have rfkill in the device) (flag) * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number */ @@ -2264,6 +2288,11 @@ enum nl80211_wowlan_triggers { NL80211_WOWLAN_TRIG_DISCONNECT, NL80211_WOWLAN_TRIG_MAGIC_PKT, NL80211_WOWLAN_TRIG_PKT_PATTERN, + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED, + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE, + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, + NL80211_WOWLAN_TRIG_RFKILL_RELEASE, /* keep last */ NUM_NL80211_WOWLAN_TRIG, diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index b0928c1..8623217 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -27,6 +27,8 @@ struct ssb_sprom { u8 et1mdcport; /* MDIO for enet1 */ u8 board_rev; /* Board revision number from SPROM. */ u8 country_code; /* Country Code */ + u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */ + u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */ u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */ u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */ u16 pa0b0; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5390e32..d17f47f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -777,6 +777,7 @@ struct cfg80211_ssid { * @n_channels: total number of channels to scan * @ie: optional information element(s) to add into Probe Request or %NULL * @ie_len: length of ie in octets + * @rates: bitmap of rates to advertise for each band * @wiphy: the wiphy this was for * @dev: the interface * @aborted: (internal) scan request was notified as aborted @@ -788,6 +789,8 @@ struct cfg80211_scan_request { const u8 *ie; size_t ie_len; + u32 rates[IEEE80211_NUM_BANDS]; + /* internal */ struct wiphy *wiphy; struct net_device *dev; @@ -1146,9 +1149,15 @@ struct cfg80211_wowlan_trig_pkt_pattern { * @magic_pkt: wake up on receiving magic packet * @patterns: wake up on receiving packet matching a pattern * @n_patterns: number of patterns + * @gtk_rekey_failure: wake up on GTK rekey failure + * @eap_identity_req: wake up on EAP identity request packet + * @four_way_handshake: wake up on 4-way handshake + * @rfkill_release: wake up when rfkill is released */ struct cfg80211_wowlan { - bool any, disconnect, magic_pkt; + bool any, disconnect, magic_pkt, gtk_rekey_failure, + eap_identity_req, four_way_handshake, + rfkill_release; struct cfg80211_wowlan_trig_pkt_pattern *patterns; int n_patterns; }; @@ -1673,11 +1682,21 @@ struct ieee80211_txrx_stypes { * @WIPHY_WOWLAN_MAGIC_PKT: supports wakeup on magic packet * (see nl80211.h) * @WIPHY_WOWLAN_DISCONNECT: supports wakeup on disconnect + * @WIPHY_WOWLAN_SUPPORTS_GTK_REKEY: supports GTK rekeying while asleep + * @WIPHY_WOWLAN_GTK_REKEY_FAILURE: supports wakeup on GTK rekey failure + * @WIPHY_WOWLAN_EAP_IDENTITY_REQ: supports wakeup on EAP identity request + * @WIPHY_WOWLAN_4WAY_HANDSHAKE: supports wakeup on 4-way handshake failure + * @WIPHY_WOWLAN_RFKILL_RELEASE: supports wakeup on RF-kill release */ enum wiphy_wowlan_support_flags { - WIPHY_WOWLAN_ANY = BIT(0), - WIPHY_WOWLAN_MAGIC_PKT = BIT(1), - WIPHY_WOWLAN_DISCONNECT = BIT(2), + WIPHY_WOWLAN_ANY = BIT(0), + WIPHY_WOWLAN_MAGIC_PKT = BIT(1), + WIPHY_WOWLAN_DISCONNECT = BIT(2), + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY = BIT(3), + WIPHY_WOWLAN_GTK_REKEY_FAILURE = BIT(4), + WIPHY_WOWLAN_EAP_IDENTITY_REQ = BIT(5), + WIPHY_WOWLAN_4WAY_HANDSHAKE = BIT(6), + WIPHY_WOWLAN_RFKILL_RELEASE = BIT(7), }; /** @@ -1742,9 +1761,13 @@ struct wiphy_wowlan_support { * this variable determines its size * @max_scan_ssids: maximum number of SSIDs the device can scan for in * any given scan + * @max_sched_scan_ssids: maximum number of SSIDs the device can scan + * for in any given scheduled scan * @max_scan_ie_len: maximum length of user-controlled IEs device can * add to probe request frames transmitted during a scan, must not * include fixed IEs like supported rates + * @max_sched_scan_ie_len: same as max_scan_ie_len, but for scheduled + * scans * @coverage_class: current coverage class * @fw_version: firmware version for ethtool reporting * @hw_version: hardware version for ethtool reporting @@ -1796,7 +1819,9 @@ struct wiphy { int bss_priv_size; u8 max_scan_ssids; + u8 max_sched_scan_ssids; u16 max_scan_ie_len; + u16 max_sched_scan_ie_len; int n_cipher_suites; const u32 *cipher_suites; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ea2c8c3..9259e97 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1586,6 +1586,20 @@ enum ieee80211_ampdu_mlme_action { }; /** + * enum ieee80211_tx_sync_type - TX sync type + * @IEEE80211_TX_SYNC_AUTH: sync TX for authentication + * (and possibly also before direct probe) + * @IEEE80211_TX_SYNC_ASSOC: sync TX for association + * @IEEE80211_TX_SYNC_ACTION: sync TX for action frame + * (not implemented yet) + */ +enum ieee80211_tx_sync_type { + IEEE80211_TX_SYNC_AUTH, + IEEE80211_TX_SYNC_ASSOC, + IEEE80211_TX_SYNC_ACTION, +}; + +/** * struct ieee80211_ops - callbacks from mac80211 to the driver * * This structure contains various callbacks that the driver may @@ -1674,6 +1688,26 @@ enum ieee80211_ampdu_mlme_action { * of the bss parameters has changed when a call is made. The callback * can sleep. * + * @tx_sync: Called before a frame is sent to an AP/GO. In the GO case, the + * driver should sync with the GO's powersaving so the device doesn't + * transmit the frame while the GO is asleep. In the regular AP case + * it may be used by drivers for devices implementing other restrictions + * on talking to APs, e.g. due to regulatory enforcement or just HW + * restrictions. + * This function is called for every authentication, association and + * action frame separately since applications might attempt to auth + * with multiple APs before chosing one to associate to. If it returns + * an error, the corresponding authentication, association or frame + * transmission is aborted and reported as having failed. It is always + * called after tuning to the correct channel. + * The callback might be called multiple times before @finish_tx_sync + * (but @finish_tx_sync will be called once for each) but in practice + * this is unlikely to happen. It can also refuse in that case if the + * driver cannot handle that situation. + * This callback can sleep. + * @finish_tx_sync: Called as a counterpart to @tx_sync, unless that returned + * an error. This callback can sleep. + * * @prepare_multicast: Prepare for multicast filter configuration. * This callback is optional, and its return value is passed * to configure_filter(). This callback must be atomic. @@ -1901,6 +1935,14 @@ struct ieee80211_ops { struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed); + + int (*tx_sync)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + const u8 *bssid, enum ieee80211_tx_sync_type type); + void (*finish_tx_sync)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *bssid, + enum ieee80211_tx_sync_type type); + u64 (*prepare_multicast)(struct ieee80211_hw *hw, struct netdev_hw_addr_list *mc_list); void (*configure_filter)(struct ieee80211_hw *hw, @@ -2613,6 +2655,20 @@ static inline void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf, } /** + * ieee80211_get_tkip_rx_p1k - get a TKIP phase 1 key for RX + * + * This function returns the TKIP phase 1 key for the given IV32 + * and transmitter address. + * + * @keyconf: the parameter passed with the set key + * @ta: TA that will be used with the key + * @iv32: IV32 to get the P1K for + * @p1k: a buffer to which the key will be written, as 5 u16 values + */ +void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, + const u8 *ta, u32 iv32, u16 *p1k); + +/** * ieee80211_get_tkip_p2k - get a TKIP phase 2 key * * This function computes the TKIP RC4 key for the IV values @@ -2973,6 +3029,10 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, * needs reprogramming of the keys during suspend. Note that due * to locking reasons, it is also only safe to call this at few * spots since it must hold the RTNL and be able to sleep. + * + * The order in which the keys are iterated matches the order + * in which they were originally installed and handed to the + * set_key callback. */ void ieee80211_iter_keys(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index ebadb9a..fd1aaf2 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -104,14 +104,22 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, const u8 *addr) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct sta_info *sta = sta_info_get(sdata, addr); + struct sta_info *sta; int i; + rcu_read_lock(); + sta = sta_info_get(sdata, addr); + if (!sta) { + rcu_read_unlock(); + return; + } + for (i = 0; i < STA_TID_NUM; i++) if (ba_rx_bitmap & BIT(i)) set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested); ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); + rcu_read_unlock(); } EXPORT_SYMBOL(ieee80211_stop_rx_ba_session); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index bfc36e9..3d1b091 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1255,6 +1255,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, */ p.uapsd = false; + if (params->queue >= local->hw.queues) + return -EINVAL; + + local->tx_conf[params->queue] = p; if (drv_conf_tx(local, params->queue, &p)) { wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d\n", diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b2d6bba..1425380 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -130,6 +130,37 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline int drv_tx_sync(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *bssid, + enum ieee80211_tx_sync_type type) +{ + int ret = 0; + + might_sleep(); + + trace_drv_tx_sync(local, sdata, bssid, type); + if (local->ops->tx_sync) + ret = local->ops->tx_sync(&local->hw, &sdata->vif, + bssid, type); + trace_drv_return_int(local, ret); + return ret; +} + +static inline void drv_finish_tx_sync(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *bssid, + enum ieee80211_tx_sync_type type) +{ + might_sleep(); + + trace_drv_finish_tx_sync(local, sdata, bssid, type); + if (local->ops->finish_tx_sync) + local->ops->finish_tx_sync(&local->hw, &sdata->vif, + bssid, type); + trace_drv_return_void(local); +} + static inline u64 drv_prepare_multicast(struct ieee80211_local *local, struct netdev_hw_addr_list *mc_list) { diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 4470f6e8..f47b00dc7 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -319,6 +319,49 @@ TRACE_EVENT(drv_bss_info_changed, ) ); +DECLARE_EVENT_CLASS(tx_sync_evt, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *bssid, + enum ieee80211_tx_sync_type type), + TP_ARGS(local, sdata, bssid, type), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __array(char, bssid, ETH_ALEN) + __field(u32, sync_type) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + memcpy(__entry->bssid, bssid, ETH_ALEN); + __entry->sync_type = type; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT " bssid:%pM type:%d", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type + ) +); + +DEFINE_EVENT(tx_sync_evt, drv_tx_sync, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *bssid, + enum ieee80211_tx_sync_type type), + TP_ARGS(local, sdata, bssid, type) +); + +DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *bssid, + enum ieee80211_tx_sync_type type), + TP_ARGS(local, sdata, bssid, type) +); + TRACE_EVENT(drv_prepare_multicast, TP_PROTO(struct ieee80211_local *local, int mc_count), diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index dda0d1a..400c09b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -323,6 +323,7 @@ struct ieee80211_work { u8 key[WLAN_KEY_LEN_WEP104]; u8 key_len, key_idx; bool privacy; + bool synced; } probe_auth; struct { struct cfg80211_bss *bss; @@ -336,6 +337,7 @@ struct ieee80211_work { u8 ssid_len; u8 supp_rates_len; bool wmm_used, use_11n, uapsd_used; + bool synced; } assoc; struct { u32 duration; @@ -746,6 +748,7 @@ struct ieee80211_local { struct workqueue_struct *workqueue; unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; + struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ spinlock_t queue_stop_reason_lock; @@ -1376,14 +1379,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, enum ieee80211_band band, u32 rate_mask, u8 channel); struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, - u8 *dst, + u8 *dst, u32 ratemask, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, bool directed); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - bool directed); + u32 ratemask, bool directed); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 739bee1..5150c6d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -278,7 +278,7 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, bool defunikey, defmultikey, defmgmtkey; if (new) - list_add(&new->list, &sdata->key_list); + list_add_tail(&new->list, &sdata->key_list); if (sta && pairwise) { rcu_assign_pointer(sta->ptk, new); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c99237c..d6470c7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -917,6 +917,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, params.aifs, params.cw_min, params.cw_max, params.txop, params.uapsd); #endif + local->tx_conf[queue] = params; if (drv_conf_tx(local, queue, ¶ms)) wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d\n", @@ -1219,7 +1220,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) } else { ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, - true); + (u32) -1, true); } ifmgd->probe_send_count++; @@ -1304,7 +1305,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, - ssid + 2, ssid[1], NULL, 0, true); + (u32) -1, ssid + 2, ssid[1], + NULL, 0, true); return skb; } @@ -2333,14 +2335,16 @@ static enum work_done_result ieee80211_probe_auth_done(struct ieee80211_work *wk, struct sk_buff *skb) { + struct ieee80211_local *local = wk->sdata->local; + if (!skb) { cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); - return WORK_DONE_DESTROY; + goto destroy; } if (wk->type == IEEE80211_WORK_AUTH) { cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); - return WORK_DONE_DESTROY; + goto destroy; } mutex_lock(&wk->sdata->u.mgd.mtx); @@ -2350,6 +2354,12 @@ ieee80211_probe_auth_done(struct ieee80211_work *wk, wk->type = IEEE80211_WORK_AUTH; wk->probe_auth.tries = 0; return WORK_DONE_REQUEUE; + destroy: + if (wk->probe_auth.synced) + drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, + IEEE80211_TX_SYNC_AUTH); + + return WORK_DONE_DESTROY; } int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, @@ -2422,6 +2432,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, struct sk_buff *skb) { + struct ieee80211_local *local = wk->sdata->local; struct ieee80211_mgmt *mgmt; struct ieee80211_rx_status *rx_status; struct ieee802_11_elems elems; @@ -2429,7 +2440,7 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, if (!skb) { cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); - return WORK_DONE_DESTROY; + goto destroy; } if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { @@ -2449,6 +2460,10 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, status = le16_to_cpu(mgmt->u.assoc_resp.status_code); if (status == WLAN_STATUS_SUCCESS) { + if (wk->assoc.synced) + drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, + IEEE80211_TX_SYNC_ASSOC); + mutex_lock(&wk->sdata->u.mgd.mtx); if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { mutex_unlock(&wk->sdata->u.mgd.mtx); @@ -2462,6 +2477,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, } cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); + destroy: + if (wk->assoc.synced) + drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, + IEEE80211_TX_SYNC_ASSOC); + return WORK_DONE_DESTROY; } diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index f87e993..6326d34 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -34,6 +34,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct ieee80211_sub_if_data *sdata; struct sta_info *sta; + if (!local->open_count) + goto suspend; + ieee80211_scan_cancel(local); if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 08a45ac..6f09eca 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -228,7 +228,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) { struct cfg80211_scan_request *req = local->scan_req; - struct ieee80211_sub_if_data *sdata = local->scan_sdata; enum ieee80211_band band; int i, ielen, n_chans; @@ -253,7 +252,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, req->ie, req->ie_len, band, - sdata->rc_rateidx_mask[band], 0); + req->rates[band], 0); local->hw_scan_req->ie_len = ielen; return true; @@ -653,6 +652,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, { int i; struct ieee80211_sub_if_data *sdata = local->scan_sdata; + enum ieee80211_band band = local->hw.conf.channel->band; for (i = 0; i < local->scan_req->n_ssids; i++) ieee80211_send_probe_req( @@ -660,7 +660,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, local->scan_req->ssids[i].ssid, local->scan_req->ssids[i].ssid_len, local->scan_req->ie, local->scan_req->ie_len, - false); + local->scan_req->rates[band], false); /* * After sending probe requests, wait for probe responses diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index cc79e69..f49d00a 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -185,6 +185,17 @@ void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf, } EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv); +void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, + const u8 *ta, u32 iv32, u16 *p1k) +{ + const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; + struct tkip_ctx ctx; + + tkip_mixing_phase1(tk, &ctx, ta, iv32); + memcpy(p1k, ctx.p1k, sizeof(ctx.p1k)); +} +EXPORT_SYMBOL(ieee80211_get_tkip_rx_p1k); + void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, struct sk_buff *skb, u8 *p2k) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5bfb80c..ddeb1b9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -799,6 +799,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) qparam.uapsd = false; + local->tx_conf[queue] = qparam; drv_conf_tx(local, queue, &qparam); } @@ -1016,7 +1017,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, } struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, - u8 *dst, + u8 *dst, u32 ratemask, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, bool directed) @@ -1049,9 +1050,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, local->hw.conf.channel->band, - sdata->rc_rateidx_mask - [local->hw.conf.channel->band], - chan); + ratemask, chan); skb = ieee80211_probereq_get(&local->hw, &sdata->vif, ssid, ssid_len, @@ -1072,12 +1071,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - bool directed) + u32 ratemask, bool directed) { struct sk_buff *skb; - skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len, - directed); + skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, + ie, ie_len, directed); if (skb) ieee80211_tx_skb(sdata, skb); } @@ -1134,7 +1133,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_hw *hw = &local->hw; struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - int res; + int res, i; #ifdef CONFIG_PM if (local->suspended) @@ -1157,27 +1156,37 @@ int ieee80211_reconfig(struct ieee80211_local *local) } #endif - /* restart hardware */ - if (local->open_count) { - /* - * Upon resume hardware can sometimes be goofy due to - * various platform / driver / bus issues, so restarting - * the device may at times not work immediately. Propagate - * the error. - */ - res = drv_start(local); - if (res) { - WARN(local->suspended, "Hardware became unavailable " - "upon resume. This could be a software issue " - "prior to suspend or a hardware issue.\n"); - return res; - } + /* setup fragmentation threshold */ + drv_set_frag_threshold(local, hw->wiphy->frag_threshold); + + /* setup RTS threshold */ + drv_set_rts_threshold(local, hw->wiphy->rts_threshold); + + /* reset coverage class */ + drv_set_coverage_class(local, hw->wiphy->coverage_class); + + /* everything else happens only if HW was up & running */ + if (!local->open_count) + goto wake_up; - ieee80211_led_radio(local, true); - ieee80211_mod_tpt_led_trig(local, - IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); + /* + * Upon resume hardware can sometimes be goofy due to + * various platform / driver / bus issues, so restarting + * the device may at times not work immediately. Propagate + * the error. + */ + res = drv_start(local); + if (res) { + WARN(local->suspended, "Hardware became unavailable " + "upon resume. This could be a software issue " + "prior to suspend or a hardware issue.\n"); + return res; } + ieee80211_led_radio(local, true); + ieee80211_mod_tpt_led_trig(local, + IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); + /* add interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && @@ -1201,11 +1210,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) } mutex_unlock(&local->sta_mtx); - /* setup fragmentation threshold */ - drv_set_frag_threshold(local, hw->wiphy->frag_threshold); - - /* setup RTS threshold */ - drv_set_rts_threshold(local, hw->wiphy->rts_threshold); + /* reconfigure tx conf */ + for (i = 0; i < hw->queues; i++) + drv_conf_tx(local, i, &local->tx_conf[i]); /* reconfigure hardware */ ieee80211_hw_config(local, ~0); @@ -1287,9 +1294,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (ieee80211_sdata_running(sdata)) ieee80211_enable_keys(sdata); -#ifdef CONFIG_PM wake_up: -#endif ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index edf8583..380b9a7 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -25,6 +25,7 @@ #include "ieee80211_i.h" #include "rate.h" +#include "driver-ops.h" #define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_MAX_TRIES 3 @@ -427,6 +428,14 @@ ieee80211_direct_probe(struct ieee80211_work *wk) struct ieee80211_sub_if_data *sdata = wk->sdata; struct ieee80211_local *local = sdata->local; + if (!wk->probe_auth.synced) { + int ret = drv_tx_sync(local, sdata, wk->filter_ta, + IEEE80211_TX_SYNC_AUTH); + if (ret) + return WORK_ACT_TIMEOUT; + } + wk->probe_auth.synced = true; + wk->probe_auth.tries++; if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", @@ -450,7 +459,8 @@ ieee80211_direct_probe(struct ieee80211_work *wk) * will not answer to direct packet in unassociated state. */ ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, - wk->probe_auth.ssid_len, NULL, 0, true); + wk->probe_auth.ssid_len, NULL, 0, + (u32) -1, true); wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; run_again(local, wk->timeout); @@ -465,6 +475,14 @@ ieee80211_authenticate(struct ieee80211_work *wk) struct ieee80211_sub_if_data *sdata = wk->sdata; struct ieee80211_local *local = sdata->local; + if (!wk->probe_auth.synced) { + int ret = drv_tx_sync(local, sdata, wk->filter_ta, + IEEE80211_TX_SYNC_AUTH); + if (ret) + return WORK_ACT_TIMEOUT; + } + wk->probe_auth.synced = true; + wk->probe_auth.tries++; if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: authentication with %pM" @@ -498,6 +516,14 @@ ieee80211_associate(struct ieee80211_work *wk) struct ieee80211_sub_if_data *sdata = wk->sdata; struct ieee80211_local *local = sdata->local; + if (!wk->assoc.synced) { + int ret = drv_tx_sync(local, sdata, wk->filter_ta, + IEEE80211_TX_SYNC_ASSOC); + if (ret) + return WORK_ACT_TIMEOUT; + } + wk->assoc.synced = true; + wk->assoc.tries++; if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { printk(KERN_DEBUG "%s: association with %pM" diff --git a/net/wireless/core.c b/net/wireless/core.c index 880dbe2..645437c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -488,6 +488,10 @@ int wiphy_register(struct wiphy *wiphy) int i; u16 ifmodes = wiphy->interface_modes; + if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && + !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY))) + return -EINVAL; + if (WARN_ON(wiphy->addresses && !wiphy->n_addresses)) return -EINVAL; @@ -918,7 +922,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, * Configure power management to the driver here so that its * correctly set also after interface type changes etc. */ - if (wdev->iftype == NL80211_IFTYPE_STATION && + if ((wdev->iftype == NL80211_IFTYPE_STATION || + wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && rdev->ops->set_power_mgmt) if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps, diff --git a/net/wireless/core.h b/net/wireless/core.h index a570ff9..8672e02 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, u16 cfg80211_calculate_bitrate(struct rate_info *rate); +int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, + const u8 *rates, unsigned int n_rates, + u32 *mask); + int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, u32 beacon_int); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6a82c89..28d2aa1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -177,6 +177,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, + [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -205,6 +206,10 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, + [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG }, + [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG }, + [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG }, + [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG }, }; /* policy for GTK rekey offload attributes */ @@ -692,8 +697,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.coverage_class); NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); + NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + dev->wiphy.max_sched_scan_ssids); NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, dev->wiphy.max_scan_ie_len); + NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + dev->wiphy.max_sched_scan_ie_len); if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); @@ -929,6 +938,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); + if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); if (dev->wiphy.wowlan.n_patterns) { struct nl80211_wowlan_pattern_support pat = { .max_patterns = dev->wiphy.wowlan.n_patterns, @@ -3306,7 +3325,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) struct nlattr *attr; struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels, i; - enum ieee80211_band band; size_t ie_len; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) @@ -3326,6 +3344,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (!n_channels) return -EINVAL; } else { + enum ieee80211_band band; n_channels = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) @@ -3386,6 +3405,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) i++; } } else { + enum ieee80211_band band; + /* all channels */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { int j; @@ -3432,6 +3453,30 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->ie_len); } + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + if (wiphy->bands[i]) + request->rates[i] = + (1 << wiphy->bands[i]->n_bitrates) - 1; + + if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) { + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_SCAN_SUPP_RATES], + tmp) { + enum ieee80211_band band = nla_type(attr); + + if (band < 0 || band > IEEE80211_NUM_BANDS) { + err = -EINVAL; + goto out_free; + } + err = ieee80211_get_ratemask(wiphy->bands[band], + nla_data(attr), + nla_len(attr), + &request->rates[band]); + if (err) + goto out_free; + } + } + request->dev = dev; request->wiphy = &rdev->wiphy; @@ -3497,7 +3542,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, tmp) n_ssids++; - if (n_ssids > wiphy->max_scan_ssids) + if (n_ssids > wiphy->max_sched_scan_ssids) return -EINVAL; if (info->attrs[NL80211_ATTR_IE]) @@ -3505,7 +3550,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, else ie_len = 0; - if (ie_len > wiphy->max_scan_ie_len) + if (ie_len > wiphy->max_sched_scan_ie_len) return -EINVAL; mutex_lock(&rdev->sched_scan_mtx); @@ -4318,25 +4363,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); struct ieee80211_supported_band *sband = wiphy->bands[ibss.channel->band]; - int i, j; + int err; - if (n_rates == 0) - return -EINVAL; - - for (i = 0; i < n_rates; i++) { - int rate = (rates[i] & 0x7f) * 5; - bool found = false; - - for (j = 0; j < sband->n_bitrates; j++) { - if (sband->bitrates[j].bitrate == rate) { - found = true; - ibss.basic_rates |= BIT(j); - break; - } - } - if (!found) - return -EINVAL; - } + err = ieee80211_get_ratemask(sband, rates, n_rates, + &ibss.basic_rates); + if (err) + return err; } if (info->attrs[NL80211_ATTR_MCAST_RATE] && @@ -5272,6 +5304,14 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); if (rdev->wowlan->magic_pkt) NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); + if (rdev->wowlan->gtk_rekey_failure) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); + if (rdev->wowlan->eap_identity_req) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); + if (rdev->wowlan->four_way_handshake) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); + if (rdev->wowlan->rfkill_release) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); if (rdev->wowlan->n_patterns) { struct nlattr *nl_pats, *nl_pat; int i, pat_len; @@ -5348,6 +5388,33 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) new_triggers.magic_pkt = true; } + if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED]) + return -EINVAL; + + if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) { + if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)) + return -EINVAL; + new_triggers.gtk_rekey_failure = true; + } + + if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) { + if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)) + return -EINVAL; + new_triggers.eap_identity_req = true; + } + + if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) { + if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)) + return -EINVAL; + new_triggers.four_way_handshake = true; + } + + if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) { + if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE)) + return -EINVAL; + new_triggers.rfkill_release = true; + } + if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { struct nlattr *pat; int n_patterns = 0; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 1c4672e..2936cb8 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -862,6 +862,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, creq->n_ssids = 0; } + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + if (wiphy->bands[i]) + creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; + rdev->scan_req = creq; err = rdev->ops->scan(wiphy, dev, creq); if (err) { diff --git a/net/wireless/util.c b/net/wireless/util.c index 4d7b83f..be75a3a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1006,3 +1006,41 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, return -EBUSY; } + +int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, + const u8 *rates, unsigned int n_rates, + u32 *mask) +{ + int i, j; + + if (!sband) + return -EINVAL; + + if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES) + return -EINVAL; + + *mask = 0; + + for (i = 0; i < n_rates; i++) { + int rate = (rates[i] & 0x7f) * 5; + bool found = false; + + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) { + found = true; + *mask |= BIT(j); + break; + } + } + if (!found) + return -EINVAL; + } + + /* + * mask must have at least one bit set here since we + * didn't accept a 0-length rates array nor allowed + * entries in the array that didn't exist + */ + + return 0; +} |