提交 e62bc9e5 编写于 作者: D David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next

John W. Linville says:

====================
Yet one more pull request for wireless updates intended for 3.11...

For the mac80211 bits, Johannes says:

"Here we have a few memory leak fixes related to BSS struct handling
mostly from Ben, including a fix for a more theoretical problem
(associating while a BSS struct times out) from myself, a compilation
warning fix from Arend, mesh fixes from Thomas, tracking the beacon
bitrate (Alex), a bandwidth change event fix (Ilan) and some initial
work for 5/10 MHz channels from Simon."

Regarding the iwlwifi bits, Johannes says:

"Emmanuel removed some unneeded/unsupported module parameters and adds a
Bluetooth 1x1 lookup-table for some upcoming products. From Alex I have
an older patch to add low-power receive support, this depended on a
mac80211 commit that only just came in with the merge from wireless-next
I did. Ilan made beacon timings better, and Eytan added some debug
statements for thermal throttling. I have a few cleanups, a fix for a
long-standing but rare warning, and, arguably the most important patch
here, the firmware API version bump for the 7260/3160 devices."

Also included is a Bluetooth pull -- Gustavo says:

"Here goes a set of patches to 3.11. The biggest work here is from Andre Guedes
on the move of the Discovery to use the new request framework. Other than that
Johan provided a bunch of fixes to the L2CAP code. The rest are just small
fixes and clean ups."

On top of all that, there are a variety of updates and fixes to
brcmfmac, rt2x00, wil6210, ath9k, ath10k, and a few others here and
there.  This also includes a pull of the wireless tree, in order to
prevent some merge conflicts.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
struct bcma_bus; struct bcma_bus;
/* main.c */ /* main.c */
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
int timeout);
int bcma_bus_register(struct bcma_bus *bus); int bcma_bus_register(struct bcma_bus *bus);
void bcma_bus_unregister(struct bcma_bus *bus); void bcma_bus_unregister(struct bcma_bus *bus);
int __init bcma_bus_early_register(struct bcma_bus *bus, int __init bcma_bus_early_register(struct bcma_bus *bus,
......
...@@ -140,8 +140,15 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) ...@@ -140,8 +140,15 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
bcma_core_chipcommon_early_init(cc); bcma_core_chipcommon_early_init(cc);
if (cc->core->id.rev >= 20) { if (cc->core->id.rev >= 20) {
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); u32 pullup = 0, pulldown = 0;
bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM43142) {
pullup = 0x402e0;
pulldown = 0x20500;
}
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, pullup);
bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, pulldown);
} }
if (cc->capabilities & BCMA_CC_CAP_PMU) if (cc->capabilities & BCMA_CC_CAP_PMU)
......
...@@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, ...@@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
} }
EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc)
{
u32 ilp_ctl, alp_hz;
if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) &
BCMA_CC_PMU_STAT_EXT_LPO_AVAIL))
return 0;
bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ,
BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT));
usleep_range(1000, 2000);
ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ);
ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK;
bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0);
alp_hz = ilp_ctl * 32768 / 4;
return (alp_hz + 50000) / 100000 * 100;
}
static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq)
{
struct bcma_bus *bus = cc->core->bus;
u32 freq_tgt_target = 0, freq_tgt_current;
u32 pll0, mask;
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM43142:
/* pmu2_xtaltab0_adfll_485 */
switch (xtalfreq) {
case 12000:
freq_tgt_target = 0x50D52;
break;
case 20000:
freq_tgt_target = 0x307FE;
break;
case 26000:
freq_tgt_target = 0x254EA;
break;
case 37400:
freq_tgt_target = 0x19EF8;
break;
case 52000:
freq_tgt_target = 0x12A75;
break;
}
break;
}
if (!freq_tgt_target) {
bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n",
xtalfreq);
return;
}
pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0);
freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >>
BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
if (freq_tgt_current == freq_tgt_target) {
bcma_debug(bus, "Target TGT frequency already set\n");
return;
}
/* Turn off PLL */
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM43142:
mask = (u32)~(BCMA_RES_4314_HT_AVAIL |
BCMA_RES_4314_MACPHY_CLK_AVAIL);
bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask);
bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask);
bcma_wait_value(cc->core, BCMA_CLKCTLST,
BCMA_CLKCTLST_HAVEHT, 0, 20000);
break;
}
pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK;
pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0);
/* Flush */
if (cc->pmu.rev >= 2)
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
/* TODO: Do we need to update OTP? */
}
static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
u32 xtalfreq = bcma_pmu_xtalfreq(cc);
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM43142:
if (xtalfreq == 0)
xtalfreq = 20000;
bcma_pmu2_pll_init0(cc, xtalfreq);
break;
}
}
static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
{ {
struct bcma_bus *bus = cc->core->bus; struct bcma_bus *bus = cc->core->bus;
...@@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) ...@@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
min_msk = 0x200D; min_msk = 0x200D;
max_msk = 0xFFFF; max_msk = 0xFFFF;
break; break;
case BCMA_CHIP_ID_BCM43142:
min_msk = BCMA_RES_4314_LPLDO_PU |
BCMA_RES_4314_PMU_SLEEP_DIS |
BCMA_RES_4314_PMU_BG_PU |
BCMA_RES_4314_CBUCK_LPOM_PU |
BCMA_RES_4314_CBUCK_PFM_PU |
BCMA_RES_4314_CLDO_PU |
BCMA_RES_4314_LPLDO2_LVM |
BCMA_RES_4314_WL_PMU_PU |
BCMA_RES_4314_LDO3P3_PU |
BCMA_RES_4314_OTP_PU |
BCMA_RES_4314_WL_PWRSW_PU |
BCMA_RES_4314_LQ_AVAIL |
BCMA_RES_4314_LOGIC_RET |
BCMA_RES_4314_MEM_SLEEP |
BCMA_RES_4314_MACPHY_RET |
BCMA_RES_4314_WL_CORE_READY;
max_msk = 0x3FFFFFFF;
break;
default: default:
bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
bus->chipinfo.id); bus->chipinfo.id);
...@@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) ...@@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
BCMA_CC_PMU_CTL_NOILPONW); BCMA_CC_PMU_CTL_NOILPONW);
bcma_pmu_pll_init(cc);
bcma_pmu_resources_init(cc); bcma_pmu_resources_init(cc);
bcma_pmu_workarounds(cc); bcma_pmu_workarounds(cc);
} }
......
...@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { ...@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ 0, }, { 0, },
}; };
......
...@@ -93,6 +93,25 @@ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, ...@@ -93,6 +93,25 @@ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
return NULL; return NULL;
} }
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
int timeout)
{
unsigned long deadline = jiffies + timeout;
u32 val;
do {
val = bcma_read32(core, reg);
if ((val & mask) == value)
return true;
cpu_relax();
udelay(10);
} while (!time_after_eq(jiffies, deadline));
bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg);
return false;
}
static void bcma_release_core_dev(struct device *dev) static void bcma_release_core_dev(struct device *dev)
{ {
struct bcma_device *core = container_of(dev, struct bcma_device, dev); struct bcma_device *core = container_of(dev, struct bcma_device, dev);
......
...@@ -503,6 +503,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) ...@@ -503,6 +503,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
case BCMA_CHIP_ID_BCM4331: case BCMA_CHIP_ID_BCM4331:
present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
break; break;
case BCMA_CHIP_ID_BCM43142:
case BCMA_CHIP_ID_BCM43224: case BCMA_CHIP_ID_BCM43224:
case BCMA_CHIP_ID_BCM43225: case BCMA_CHIP_ID_BCM43225:
/* for these chips OTP is always available */ /* for these chips OTP is always available */
......
...@@ -1619,6 +1619,7 @@ static struct usb_driver btusb_driver = { ...@@ -1619,6 +1619,7 @@ static struct usb_driver btusb_driver = {
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = btusb_suspend, .suspend = btusb_suspend,
.resume = btusb_resume, .resume = btusb_resume,
.reset_resume = btusb_resume,
#endif #endif
.id_table = btusb_table, .id_table = btusb_table,
.supports_autosuspend = 1, .supports_autosuspend = 1,
......
...@@ -54,7 +54,6 @@ static int ath10k_send_key(struct ath10k_vif *arvif, ...@@ -54,7 +54,6 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break; break;
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
arg.key_cipher = WMI_CIPHER_TKIP; arg.key_cipher = WMI_CIPHER_TKIP;
arg.key_txmic_len = 8; arg.key_txmic_len = 8;
arg.key_rxmic_len = 8; arg.key_rxmic_len = 8;
...@@ -237,6 +236,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) ...@@ -237,6 +236,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
case NL80211_CHAN_WIDTH_40: case NL80211_CHAN_WIDTH_40:
phymode = MODE_11NG_HT40; phymode = MODE_11NG_HT40;
break; break;
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_160:
...@@ -258,6 +259,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) ...@@ -258,6 +259,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80:
phymode = MODE_11AC_VHT80; phymode = MODE_11AC_VHT80;
break; break;
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_160:
phymode = MODE_UNKNOWN; phymode = MODE_UNKNOWN;
...@@ -2721,30 +2724,30 @@ static const struct ieee80211_channel ath10k_2ghz_channels[] = { ...@@ -2721,30 +2724,30 @@ static const struct ieee80211_channel ath10k_2ghz_channels[] = {
}; };
static const struct ieee80211_channel ath10k_5ghz_channels[] = { static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(36, 5180, 14), CHAN5G(36, 5180, 0),
CHAN5G(40, 5200, 15), CHAN5G(40, 5200, 0),
CHAN5G(44, 5220, 16), CHAN5G(44, 5220, 0),
CHAN5G(48, 5240, 17), CHAN5G(48, 5240, 0),
CHAN5G(52, 5260, 18), CHAN5G(52, 5260, 0),
CHAN5G(56, 5280, 19), CHAN5G(56, 5280, 0),
CHAN5G(60, 5300, 20), CHAN5G(60, 5300, 0),
CHAN5G(64, 5320, 21), CHAN5G(64, 5320, 0),
CHAN5G(100, 5500, 22), CHAN5G(100, 5500, 0),
CHAN5G(104, 5520, 23), CHAN5G(104, 5520, 0),
CHAN5G(108, 5540, 24), CHAN5G(108, 5540, 0),
CHAN5G(112, 5560, 25), CHAN5G(112, 5560, 0),
CHAN5G(116, 5580, 26), CHAN5G(116, 5580, 0),
CHAN5G(120, 5600, 27), CHAN5G(120, 5600, 0),
CHAN5G(124, 5620, 28), CHAN5G(124, 5620, 0),
CHAN5G(128, 5640, 29), CHAN5G(128, 5640, 0),
CHAN5G(132, 5660, 30), CHAN5G(132, 5660, 0),
CHAN5G(136, 5680, 31), CHAN5G(136, 5680, 0),
CHAN5G(140, 5700, 32), CHAN5G(140, 5700, 0),
CHAN5G(149, 5745, 33), CHAN5G(149, 5745, 0),
CHAN5G(153, 5765, 34), CHAN5G(153, 5765, 0),
CHAN5G(157, 5785, 35), CHAN5G(157, 5785, 0),
CHAN5G(161, 5805, 36), CHAN5G(161, 5805, 0),
CHAN5G(165, 5825, 37), CHAN5G(165, 5825, 0),
}; };
static struct ieee80211_rate ath10k_rates[] = { static struct ieee80211_rate ath10k_rates[] = {
......
...@@ -1883,9 +1883,10 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num) ...@@ -1883,9 +1883,10 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num)
ath10k_warn("request_irq(%d) failed %d\n", ath10k_warn("request_irq(%d) failed %d\n",
ar_pci->pdev->irq + i, ret); ar_pci->pdev->irq + i, ret);
for (; i >= MSI_ASSIGN_CE_INITIAL; i--) for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--)
free_irq(ar_pci->pdev->irq, ar); free_irq(ar_pci->pdev->irq + i, ar);
free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar);
pci_disable_msi(ar_pci->pdev); pci_disable_msi(ar_pci->pdev);
return ret; return ret;
} }
......
...@@ -3606,7 +3606,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) ...@@ -3606,7 +3606,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
* SWITCH_TABLE_COM_SPDT_WLAN_IDLE * SWITCH_TABLE_COM_SPDT_WLAN_IDLE
*/ */
if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) { if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565(ah)) {
value = ar9003_switch_com_spdt_get(ah, is2ghz); value = ar9003_switch_com_spdt_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
AR_SWITCH_TABLE_COM_SPDT_ALL, value); AR_SWITCH_TABLE_COM_SPDT_ALL, value);
...@@ -4059,8 +4059,9 @@ static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah) ...@@ -4059,8 +4059,9 @@ static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
{ {
u32 data, ko, kg; u32 data, ko, kg;
if (!AR_SREV_9462_20(ah)) if (!AR_SREV_9462_20_OR_LATER(ah))
return; return;
ar9300_otp_read_word(ah, 1, &data); ar9300_otp_read_word(ah, 1, &data);
ko = data & 0xff; ko = data & 0xff;
kg = (data >> 8) & 0xff; kg = (data >> 8) & 0xff;
...@@ -4752,7 +4753,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah, ...@@ -4752,7 +4753,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah,
AR_PHY_TPC_19_ALPHA_THERM, temp_slope); AR_PHY_TPC_19_ALPHA_THERM, temp_slope);
} }
if (AR_SREV_9462_20(ah)) if (AR_SREV_9462_20_OR_LATER(ah))
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
AR_PHY_TPC_19_B1_ALPHA_THERM, temp_slope); AR_PHY_TPC_19_B1_ALPHA_THERM, temp_slope);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "ar955x_1p0_initvals.h" #include "ar955x_1p0_initvals.h"
#include "ar9580_1p0_initvals.h" #include "ar9580_1p0_initvals.h"
#include "ar9462_2p0_initvals.h" #include "ar9462_2p0_initvals.h"
#include "ar9462_2p1_initvals.h"
#include "ar9565_1p0_initvals.h" #include "ar9565_1p0_initvals.h"
/* General hardware code for the AR9003 hadware family */ /* General hardware code for the AR9003 hadware family */
...@@ -197,6 +198,31 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ...@@ -197,6 +198,31 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9485_1_1_pcie_phy_clkreq_disable_L1); ar9485_1_1_pcie_phy_clkreq_disable_L1);
} else if (AR_SREV_9462_21(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9462_2p1_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9462_2p1_mac_postamble);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9462_2p1_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9462_2p1_baseband_postamble);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9462_2p1_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9462_2p1_radio_postamble);
INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
ar9462_2p1_radio_postamble_sys2ant);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9462_2p1_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9462_2p1_soc_postamble);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p1_common_rx_gain);
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9462_2p1_modes_fast_clock);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
ar9462_2p1_baseband_core_txfir_coeff_japan_2484);
} else if (AR_SREV_9462_20(ah)) { } else if (AR_SREV_9462_20(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core);
...@@ -407,6 +433,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) ...@@ -407,6 +433,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
else if (AR_SREV_9580(ah)) else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table); ar9580_1p0_lowest_ob_db_tx_gain_table);
else if (AR_SREV_9462_21(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_2p1_modes_low_ob_db_tx_gain);
else if (AR_SREV_9462_20(ah)) else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_low_ob_db_tx_gain_table_2p0); ar9462_modes_low_ob_db_tx_gain_table_2p0);
...@@ -438,6 +467,9 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) ...@@ -438,6 +467,9 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
else if (AR_SREV_9550(ah)) else if (AR_SREV_9550(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar955x_1p0_modes_no_xpa_tx_gain_table); ar955x_1p0_modes_no_xpa_tx_gain_table);
else if (AR_SREV_9462_21(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_2p1_modes_high_ob_db_tx_gain);
else if (AR_SREV_9462_20(ah)) else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_high_ob_db_tx_gain_table_2p0); ar9462_modes_high_ob_db_tx_gain_table_2p0);
...@@ -507,6 +539,12 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) ...@@ -507,6 +539,12 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah)
else if (AR_SREV_9580(ah)) else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_mixed_ob_db_tx_gain_table); ar9580_1p0_mixed_ob_db_tx_gain_table);
else if (AR_SREV_9462_21(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_2p1_modes_mix_ob_db_tx_gain);
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_mix_ob_db_tx_gain_table_2p0);
else else
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_mixed_ob_db_tx_gain_table_2p2); ar9300Modes_mixed_ob_db_tx_gain_table_2p2);
...@@ -584,6 +622,9 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) ...@@ -584,6 +622,9 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
} else if (AR_SREV_9580(ah)) } else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table); ar9580_1p0_rx_gain_table);
else if (AR_SREV_9462_21(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p1_common_rx_gain);
else if (AR_SREV_9462_20(ah)) else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_rx_gain_table_2p0); ar9462_common_rx_gain_table_2p0);
...@@ -606,6 +647,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) ...@@ -606,6 +647,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
else if (AR_SREV_9485_11(ah)) else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1); ar9485Common_wo_xlna_rx_gain_1_1);
else if (AR_SREV_9462_21(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p1_common_wo_xlna_rx_gain);
else if (AR_SREV_9462_20(ah)) else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_wo_xlna_rx_gain_table_2p0); ar9462_common_wo_xlna_rx_gain_table_2p0);
...@@ -627,7 +671,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) ...@@ -627,7 +671,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
{ {
if (AR_SREV_9462_20(ah)) { if (AR_SREV_9462_21(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p1_common_mixed_rx_gain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core,
ar9462_2p1_baseband_core_mix_rxgain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
ar9462_2p1_baseband_postamble_mix_rxgain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
ar9462_2p1_baseband_postamble_5g_xlna);
} else if (AR_SREV_9462_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_mixed_rx_gain_table_2p0); ar9462_common_mixed_rx_gain_table_2p0);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core,
...@@ -641,7 +694,12 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) ...@@ -641,7 +694,12 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) static void ar9003_rx_gain_table_mode3(struct ath_hw *ah)
{ {
if (AR_SREV_9462_20(ah)) { if (AR_SREV_9462_21(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p1_common_5g_xlna_only_rx_gain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
ar9462_2p1_baseband_postamble_5g_xlna);
} else if (AR_SREV_9462_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_2p0_5g_xlna_only_rxgain); ar9462_2p0_5g_xlna_only_rxgain);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
......
...@@ -743,7 +743,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, ...@@ -743,7 +743,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
if (i == ATH_INI_POST && AR_SREV_9462_20(ah)) if (i == ATH_INI_POST && AR_SREV_9462_20_OR_LATER(ah))
ar9003_hw_prog_ini(ah, ar9003_hw_prog_ini(ah,
&ah->ini_radio_post_sys2ant, &ah->ini_radio_post_sys2ant,
modesIndex); modesIndex);
...@@ -754,7 +754,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, ...@@ -754,7 +754,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
*/ */
REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
if (AR_SREV_9462_20(ah)) { if (AR_SREV_9462_20_OR_LATER(ah)) {
/* /*
* CUS217 mix LNA mode. * CUS217 mix LNA mode.
*/ */
...@@ -1512,7 +1512,7 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah, ...@@ -1512,7 +1512,7 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
if (AR_SREV_9462_20(ah)) if (AR_SREV_9462_20_OR_LATER(ah))
ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant, ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant,
modesIndex); modesIndex);
......
...@@ -954,7 +954,7 @@ ...@@ -954,7 +954,7 @@
#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208) #define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c) #define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9462(ah) ? \ #define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_9462_20_OR_LATER(ah) ? \
0x280 : 0x240)) 0x280 : 0x240))
#define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240) #define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240)
#define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff #define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff
...@@ -1048,7 +1048,7 @@ ...@@ -1048,7 +1048,7 @@
#define AR_GLB_GPIO_CONTROL (AR_GLB_BASE) #define AR_GLB_GPIO_CONTROL (AR_GLB_BASE)
#define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44) #define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44)
#define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \ #define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \
(AR_SREV_9462_20(_ah) ? 0x4c : 0x50)) (AR_SREV_9462_20_OR_LATER(_ah) ? 0x4c : 0x50))
#define AR_GLB_STATUS (AR_GLB_BASE + 0x48) #define AR_GLB_STATUS (AR_GLB_BASE + 0x48)
/* /*
......
...@@ -879,6 +879,69 @@ static const u32 ar9462_2p0_radio_postamble[][5] = { ...@@ -879,6 +879,69 @@ static const u32 ar9462_2p0_radio_postamble[][5] = {
{0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
}; };
static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
{0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de},
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
{0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400},
{0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402},
{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
{0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603},
{0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02},
{0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04},
{0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20},
{0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20},
{0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22},
{0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24},
{0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640},
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660},
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861},
{0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81},
{0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83},
{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84},
{0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3},
{0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5},
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9},
{0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb},
{0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec},
{0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0},
{0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4},
{0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
{0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
{0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
{0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
{0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
{0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
{0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
{0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
{0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
{0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
{0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
{0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
};
static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
......
此差异已折叠。
...@@ -634,6 +634,7 @@ void ath_ant_comb_update(struct ath_softc *sc); ...@@ -634,6 +634,7 @@ void ath_ant_comb_update(struct ath_softc *sc);
#define ATH9K_PCI_CUS198 0x0001 #define ATH9K_PCI_CUS198 0x0001
#define ATH9K_PCI_CUS230 0x0002 #define ATH9K_PCI_CUS230 0x0002
#define ATH9K_PCI_CUS217 0x0004 #define ATH9K_PCI_CUS217 0x0004
#define ATH9K_PCI_WOW 0x0008
/* /*
* Default cache line size, in bytes. * Default cache line size, in bytes.
......
...@@ -234,10 +234,15 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, ...@@ -234,10 +234,15 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
struct sk_buff *skb; struct sk_buff *skb;
while ((skb = __skb_dequeue(queue)) != NULL) { while ((skb = __skb_dequeue(queue)) != NULL) {
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
int ln = skb->len;
#endif
ath9k_htc_txcompletion_cb(hif_dev->htc_handle, ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
skb, txok); skb, txok);
if (txok) if (txok) {
TX_STAT_INC(skb_success); TX_STAT_INC(skb_success);
TX_STAT_ADD(skb_success_bytes, ln);
}
else else
TX_STAT_INC(skb_failed); TX_STAT_INC(skb_failed);
} }
...@@ -620,6 +625,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, ...@@ -620,6 +625,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
err: err:
for (i = 0; i < pool_index; i++) { for (i = 0; i < pool_index; i++) {
RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len);
ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
skb_pool[i]->len, USB_WLAN_RX_PIPE); skb_pool[i]->len, USB_WLAN_RX_PIPE);
RX_STAT_INC(skb_completed); RX_STAT_INC(skb_completed);
......
...@@ -324,7 +324,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) ...@@ -324,7 +324,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
#ifdef CONFIG_ATH9K_HTC_DEBUGFS #ifdef CONFIG_ATH9K_HTC_DEBUGFS
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++)
#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c += a)
#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++
#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
...@@ -337,6 +339,7 @@ struct ath_tx_stats { ...@@ -337,6 +339,7 @@ struct ath_tx_stats {
u32 buf_completed; u32 buf_completed;
u32 skb_queued; u32 skb_queued;
u32 skb_success; u32 skb_success;
u32 skb_success_bytes;
u32 skb_failed; u32 skb_failed;
u32 cab_queued; u32 cab_queued;
u32 queue_stats[IEEE80211_NUM_ACS]; u32 queue_stats[IEEE80211_NUM_ACS];
...@@ -345,6 +348,7 @@ struct ath_tx_stats { ...@@ -345,6 +348,7 @@ struct ath_tx_stats {
struct ath_rx_stats { struct ath_rx_stats {
u32 skb_allocated; u32 skb_allocated;
u32 skb_completed; u32 skb_completed;
u32 skb_completed_bytes;
u32 skb_dropped; u32 skb_dropped;
u32 err_crc; u32 err_crc;
u32 err_decrypt_crc; u32 err_decrypt_crc;
...@@ -362,10 +366,20 @@ struct ath9k_debug { ...@@ -362,10 +366,20 @@ struct ath9k_debug {
struct ath_rx_stats rx_stats; struct ath_rx_stats rx_stats;
}; };
void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data);
int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int sset);
void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data);
#else #else
#define TX_STAT_INC(c) do { } while (0) #define TX_STAT_INC(c) do { } while (0)
#define TX_STAT_ADD(c, a) do { } while (0)
#define RX_STAT_INC(c) do { } while (0) #define RX_STAT_INC(c) do { } while (0)
#define RX_STAT_ADD(c, a) do { } while (0)
#define CAB_STAT_INC do { } while (0) #define CAB_STAT_INC do { } while (0)
#define TX_QSTAT_INC(c) do { } while (0) #define TX_QSTAT_INC(c) do { } while (0)
...@@ -583,6 +597,8 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, ...@@ -583,6 +597,8 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv);
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS
void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_init_leds(struct ath9k_htc_priv *priv);
void ath9k_deinit_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
......
...@@ -496,21 +496,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, ...@@ -496,21 +496,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
ssize_t retval = 0; ssize_t retval = 0;
char *buf; char *buf;
/* pBase = ath9k_htc_get_eeprom_base(priv);
* This can be done since all the 3 EEPROM families have the
* same base header upto a certain point, and we are interested in
* the data only upto that point.
*/
if (AR_SREV_9271(priv->ah))
pBase = (struct base_eep_header *)
&priv->ah->eeprom.map4k.baseEepHeader;
else if (priv->ah->hw_version.usbdev == AR9280_USB)
pBase = (struct base_eep_header *)
&priv->ah->eeprom.def.baseEepHeader;
else if (priv->ah->hw_version.usbdev == AR9287_USB)
pBase = (struct base_eep_header *)
&priv->ah->eeprom.map9287.baseEepHeader;
if (pBase == NULL) { if (pBase == NULL) {
ath_err(common, "Unknown EEPROM type\n"); ath_err(common, "Unknown EEPROM type\n");
...@@ -916,6 +902,87 @@ static const struct file_operations fops_modal_eeprom = { ...@@ -916,6 +902,87 @@ static const struct file_operations fops_modal_eeprom = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
/* Ethtool support for get-stats */
#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx_pkts_nic",
"tx_bytes_nic",
"rx_pkts_nic",
"rx_bytes_nic",
AMKSTR(d_tx_pkts),
"d_rx_crc_err",
"d_rx_decrypt_crc_err",
"d_rx_phy_err",
"d_rx_mic_err",
"d_rx_pre_delim_crc_err",
"d_rx_post_delim_crc_err",
"d_rx_decrypt_busy_err",
"d_rx_phyerr_radar",
"d_rx_phyerr_ofdm_timing",
"d_rx_phyerr_cck_timing",
};
#define ATH9K_HTC_SSTATS_LEN ARRAY_SIZE(ath9k_htc_gstrings_stats)
void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data)
{
if (sset == ETH_SS_STATS)
memcpy(data, *ath9k_htc_gstrings_stats,
sizeof(ath9k_htc_gstrings_stats));
}
int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int sset)
{
if (sset == ETH_SS_STATS)
return ATH9K_HTC_SSTATS_LEN;
return 0;
}
#define STXBASE priv->debug.tx_stats
#define SRXBASE priv->debug.rx_stats
#define ASTXQ(a) \
data[i++] = STXBASE.a[IEEE80211_AC_BE]; \
data[i++] = STXBASE.a[IEEE80211_AC_BK]; \
data[i++] = STXBASE.a[IEEE80211_AC_VI]; \
data[i++] = STXBASE.a[IEEE80211_AC_VO]
void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data)
{
struct ath9k_htc_priv *priv = hw->priv;
int i = 0;
data[i++] = STXBASE.skb_success;
data[i++] = STXBASE.skb_success_bytes;
data[i++] = SRXBASE.skb_completed;
data[i++] = SRXBASE.skb_completed_bytes;
ASTXQ(queue_stats);
data[i++] = SRXBASE.err_crc;
data[i++] = SRXBASE.err_decrypt_crc;
data[i++] = SRXBASE.err_phy;
data[i++] = SRXBASE.err_mic;
data[i++] = SRXBASE.err_pre_delim;
data[i++] = SRXBASE.err_post_delim;
data[i++] = SRXBASE.err_decrypt_busy;
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_RADAR];
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_OFDM_TIMING];
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_CCK_TIMING];
WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
}
int ath9k_htc_init_debug(struct ath_hw *ah) int ath9k_htc_init_debug(struct ath_hw *ah)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
......
...@@ -701,8 +701,10 @@ static const struct ieee80211_iface_limit if_limits[] = { ...@@ -701,8 +701,10 @@ static const struct ieee80211_iface_limit if_limits[] = {
{ .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT) }, BIT(NL80211_IFTYPE_P2P_CLIENT) },
{ .max = 2, .types = BIT(NL80211_IFTYPE_AP) | { .max = 2, .types = BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) | #ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) }, BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_P2P_GO) },
}; };
static const struct ieee80211_iface_combination if_comb = { static const struct ieee80211_iface_combination if_comb = {
...@@ -716,6 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, ...@@ -716,6 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw) struct ieee80211_hw *hw)
{ {
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
struct base_eep_header *pBase;
hw->flags = IEEE80211_HW_SIGNAL_DBM | hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_AMPDU_AGGREGATION |
...@@ -771,6 +774,12 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, ...@@ -771,6 +774,12 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
&priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
} }
pBase = ath9k_htc_get_eeprom_base(priv);
if (pBase) {
hw->wiphy->available_antennas_rx = pBase->rxMask;
hw->wiphy->available_antennas_tx = pBase->txMask;
}
SET_IEEE80211_PERM_ADDR(hw, common->macaddr); SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
} }
......
...@@ -1183,7 +1183,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1183,7 +1183,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->htc_pm_lock); mutex_lock(&priv->htc_pm_lock);
priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
if (priv->ps_idle) if (!priv->ps_idle)
chip_reset = true; chip_reset = true;
mutex_unlock(&priv->htc_pm_lock); mutex_unlock(&priv->htc_pm_lock);
...@@ -1774,6 +1774,43 @@ static int ath9k_htc_get_stats(struct ieee80211_hw *hw, ...@@ -1774,6 +1774,43 @@ static int ath9k_htc_get_stats(struct ieee80211_hw *hw,
return 0; return 0;
} }
struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv)
{
struct base_eep_header *pBase = NULL;
/*
* This can be done since all the 3 EEPROM families have the
* same base header upto a certain point, and we are interested in
* the data only upto that point.
*/
if (AR_SREV_9271(priv->ah))
pBase = (struct base_eep_header *)
&priv->ah->eeprom.map4k.baseEepHeader;
else if (priv->ah->hw_version.usbdev == AR9280_USB)
pBase = (struct base_eep_header *)
&priv->ah->eeprom.def.baseEepHeader;
else if (priv->ah->hw_version.usbdev == AR9287_USB)
pBase = (struct base_eep_header *)
&priv->ah->eeprom.map9287.baseEepHeader;
return pBase;
}
static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
u32 *rx_ant)
{
struct ath9k_htc_priv *priv = hw->priv;
struct base_eep_header *pBase = ath9k_htc_get_eeprom_base(priv);
if (pBase) {
*tx_ant = pBase->txMask;
*rx_ant = pBase->rxMask;
} else {
*tx_ant = 0;
*rx_ant = 0;
}
return 0;
}
struct ieee80211_ops ath9k_htc_ops = { struct ieee80211_ops ath9k_htc_ops = {
.tx = ath9k_htc_tx, .tx = ath9k_htc_tx,
.start = ath9k_htc_start, .start = ath9k_htc_start,
...@@ -1799,4 +1836,11 @@ struct ieee80211_ops ath9k_htc_ops = { ...@@ -1799,4 +1836,11 @@ struct ieee80211_ops ath9k_htc_ops = {
.set_coverage_class = ath9k_htc_set_coverage_class, .set_coverage_class = ath9k_htc_set_coverage_class,
.set_bitrate_mask = ath9k_htc_set_bitrate_mask, .set_bitrate_mask = ath9k_htc_set_bitrate_mask,
.get_stats = ath9k_htc_get_stats, .get_stats = ath9k_htc_get_stats,
.get_antenna = ath9k_htc_get_antenna,
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
.get_et_sset_count = ath9k_htc_get_et_sset_count,
.get_et_stats = ath9k_htc_get_et_stats,
.get_et_strings = ath9k_htc_get_et_strings,
#endif
}; };
...@@ -2599,7 +2599,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -2599,7 +2599,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
pCap->hw_caps |= ATH9K_HW_CAP_MCI; pCap->hw_caps |= ATH9K_HW_CAP_MCI;
if (AR_SREV_9462_20(ah)) if (AR_SREV_9462_20_OR_LATER(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT; pCap->hw_caps |= ATH9K_HW_CAP_RTT;
} }
......
...@@ -837,6 +837,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -837,6 +837,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) &&
(sc->driver_data & ATH9K_PCI_WOW) &&
device_can_wakeup(sc->dev)) device_can_wakeup(sc->dev))
hw->wiphy->wowlan = &ath9k_wowlan_support; hw->wiphy->wowlan = &ath9k_wowlan_support;
......
...@@ -79,6 +79,63 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { ...@@ -79,6 +79,63 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
0x6661), 0x6661),
.driver_data = ATH9K_PCI_CUS217 }, .driver_data = ATH9K_PCI_CUS217 },
/* AR9462 with WoW support */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
PCI_VENDOR_ID_ATHEROS,
0x3117),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
PCI_VENDOR_ID_LENOVO,
0x3214),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
PCI_VENDOR_ID_ATTANSIC,
0x0091),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
PCI_VENDOR_ID_AZWAVE,
0x2110),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
PCI_VENDOR_ID_ASUSTEK,
0x850E),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
0x11AD, /* LITEON */
0x6631),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
0x11AD, /* LITEON */
0x6641),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
PCI_VENDOR_ID_HP,
0x1864),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
0x14CD, /* USI */
0x0063),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
0x14CD, /* USI */
0x0064),
.driver_data = ATH9K_PCI_WOW },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
0x10CF, /* Fujitsu */
0x1783),
.driver_data = ATH9K_PCI_WOW },
{ PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */
{ PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */
{ PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */ { PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */
......
...@@ -806,6 +806,7 @@ ...@@ -806,6 +806,7 @@
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
#define AR_SREV_VERSION_9462 0x280 #define AR_SREV_VERSION_9462 0x280
#define AR_SREV_REVISION_9462_20 2 #define AR_SREV_REVISION_9462_20 2
#define AR_SREV_REVISION_9462_21 3
#define AR_SREV_VERSION_9565 0x2C0 #define AR_SREV_VERSION_9565 0x2C0
#define AR_SREV_REVISION_9565_10 0 #define AR_SREV_REVISION_9565_10 0
#define AR_SREV_VERSION_9550 0x400 #define AR_SREV_VERSION_9550 0x400
...@@ -911,10 +912,18 @@ ...@@ -911,10 +912,18 @@
#define AR_SREV_9462(_ah) \ #define AR_SREV_9462(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462)) (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
#define AR_SREV_9462_20(_ah) \ #define AR_SREV_9462_20(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
#define AR_SREV_9462_21(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21))
#define AR_SREV_9462_20_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
#define AR_SREV_9462_21_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21))
#define AR_SREV_9565(_ah) \ #define AR_SREV_9565(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
......
...@@ -1673,6 +1673,8 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) ...@@ -1673,6 +1673,8 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return; return;
rcu_read_lock();
ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
...@@ -1711,8 +1713,10 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) ...@@ -1711,8 +1713,10 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (ac == last_ac || if (ac == last_ac ||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return; break;
} }
rcu_read_unlock();
} }
/***********/ /***********/
...@@ -1778,9 +1782,13 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, ...@@ -1778,9 +1782,13 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
} }
if (!internal) { if (!internal) {
txq->axq_depth++; while (bf) {
if (bf_is_ampdu_not_probing(bf)) txq->axq_depth++;
txq->axq_ampdu_depth++; if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth++;
bf = bf->bf_lastbf->bf_next;
}
} }
} }
......
...@@ -621,7 +621,8 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, ...@@ -621,7 +621,8 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
return NULL; return NULL;
} }
static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len) static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len,
int vring_index)
{ {
wil_desc_addr_set(&d->dma.addr, pa); wil_desc_addr_set(&d->dma.addr, pa);
d->dma.ip_length = 0; d->dma.ip_length = 0;
...@@ -630,7 +631,7 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len) ...@@ -630,7 +631,7 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len)
d->dma.error = 0; d->dma.error = 0;
d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
d->dma.length = cpu_to_le16((u16)len); d->dma.length = cpu_to_le16((u16)len);
d->dma.d0 = 0; d->dma.d0 = (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
d->mac.d[0] = 0; d->mac.d[0] = 0;
d->mac.d[1] = 0; d->mac.d[1] = 0;
d->mac.d[2] = 0; d->mac.d[2] = 0;
...@@ -684,7 +685,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, ...@@ -684,7 +685,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
if (unlikely(dma_mapping_error(dev, pa))) if (unlikely(dma_mapping_error(dev, pa)))
return -EINVAL; return -EINVAL;
/* 1-st segment */ /* 1-st segment */
wil_tx_desc_map(d, pa, skb_headlen(skb)); wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index);
d->mac.d[2] |= ((nr_frags + 1) << d->mac.d[2] |= ((nr_frags + 1) <<
MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
if (nr_frags) if (nr_frags)
...@@ -701,15 +702,14 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, ...@@ -701,15 +702,14 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev, pa))) if (unlikely(dma_mapping_error(dev, pa)))
goto dma_error; goto dma_error;
wil_tx_desc_map(d, pa, len); wil_tx_desc_map(d, pa, len, vring_index);
vring->ctx[i] = NULL; vring->ctx[i] = NULL;
*_d = *d; *_d = *d;
} }
/* for the last seg only */ /* for the last seg only */
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS);
d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS);
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
*_d = *d; *_d = *d;
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4, wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
......
...@@ -201,6 +201,10 @@ struct vring_tx_mac { ...@@ -201,6 +201,10 @@ struct vring_tx_mac {
#define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 #define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1
#define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 #define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100
#define DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS 9
#define DMA_CFG_DESC_TX_0_CMD_MARK_WB_LEN 1
#define DMA_CFG_DESC_TX_0_CMD_MARK_WB_MSK 0x200
#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10
#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1
#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400
......
...@@ -31,12 +31,6 @@ config B43_BCMA ...@@ -31,12 +31,6 @@ config B43_BCMA
depends on B43 && (BCMA = y || BCMA = B43) depends on B43 && (BCMA = y || BCMA = B43)
default y default y
config B43_BCMA_EXTRA
bool "Hardware support that overlaps with the brcmsmac driver"
depends on B43_BCMA
default n if BRCMSMAC
default y
config B43_SSB config B43_SSB
bool bool
depends on B43 && (SSB = y || SSB = B43) depends on B43 && (SSB = y || SSB = B43)
......
...@@ -113,13 +113,15 @@ static int b43_modparam_pio = 0; ...@@ -113,13 +113,15 @@ static int b43_modparam_pio = 0;
module_param_named(pio, b43_modparam_pio, int, 0644); module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
static int modparam_allhwsupport = !IS_ENABLED(CONFIG_BRCMSMAC);
module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)");
#ifdef CONFIG_B43_BCMA #ifdef CONFIG_B43_BCMA
static const struct bcma_device_id b43_bcma_tbl[] = { static const struct bcma_device_id b43_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
#ifdef CONFIG_B43_BCMA_EXTRA
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
#endif
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
BCMA_CORETABLE_END BCMA_CORETABLE_END
}; };
...@@ -5396,6 +5398,12 @@ static int b43_bcma_probe(struct bcma_device *core) ...@@ -5396,6 +5398,12 @@ static int b43_bcma_probe(struct bcma_device *core)
struct b43_wl *wl; struct b43_wl *wl;
int err; int err;
if (!modparam_allhwsupport &&
(core->id.rev == 0x17 || core->id.rev == 0x18)) {
pr_err("Support for cores revisions 0x17 and 0x18 disabled by module param allhwsupport=0. Try b43.allhwsupport=1\n");
return -ENOTSUPP;
}
dev = b43_bus_dev_bcma_init(core); dev = b43_bus_dev_bcma_init(core);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
......
...@@ -162,7 +162,7 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) ...@@ -162,7 +162,7 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
return 0; return 0;
} }
int static int
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
{ {
int err = 0, i; int err = 0, i;
...@@ -193,12 +193,33 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) ...@@ -193,12 +193,33 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
return err; return err;
} }
static int
brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
{
uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
if (bar0 != sdiodev->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
return err;
sdiodev->sbwad = bar0;
}
*addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (width == 4)
*addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
return 0;
}
int int
brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
void *data, bool write) void *data, bool write)
{ {
u8 func_num, reg_size; u8 func_num, reg_size;
u32 bar;
s32 retry = 0; s32 retry = 0;
int ret; int ret;
...@@ -218,18 +239,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, ...@@ -218,18 +239,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
func_num = SDIO_FUNC_1; func_num = SDIO_FUNC_1;
reg_size = 4; reg_size = 4;
/* Set the window for SB core register */ brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
if (bar != sdiodev->sbwad) {
ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar);
if (ret != 0) {
memset(data, 0xFF, reg_size);
return ret;
}
sdiodev->sbwad = bar;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
} }
do { do {
...@@ -321,10 +331,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, ...@@ -321,10 +331,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
bool write, u32 addr, struct sk_buff_head *pktlist) bool write, u32 addr, struct sk_buff_head *pktlist)
{ {
unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
unsigned int max_blks, max_req_sz; unsigned int max_blks, max_req_sz, orig_offset, dst_offset;
unsigned short max_seg_sz, seg_sz; unsigned short max_seg_sz, seg_sz;
unsigned char *pkt_data; unsigned char *pkt_data, *orig_data, *dst_data;
struct sk_buff *pkt_next = NULL; struct sk_buff *pkt_next = NULL, *local_pkt_next;
struct sk_buff_head local_list, *target_list;
struct mmc_request mmc_req; struct mmc_request mmc_req;
struct mmc_command mmc_cmd; struct mmc_command mmc_cmd;
struct mmc_data mmc_dat; struct mmc_data mmc_dat;
...@@ -361,6 +372,32 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, ...@@ -361,6 +372,32 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
req_sz); req_sz);
} }
target_list = pktlist;
/* for host with broken sg support, prepare a page aligned list */
__skb_queue_head_init(&local_list);
if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
req_sz = 0;
skb_queue_walk(pktlist, pkt_next)
req_sz += pkt_next->len;
req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize);
while (req_sz > PAGE_SIZE) {
pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
if (pkt_next == NULL) {
ret = -ENOMEM;
goto exit;
}
__skb_queue_tail(&local_list, pkt_next);
req_sz -= PAGE_SIZE;
}
pkt_next = brcmu_pkt_buf_get_skb(req_sz);
if (pkt_next == NULL) {
ret = -ENOMEM;
goto exit;
}
__skb_queue_tail(&local_list, pkt_next);
target_list = &local_list;
}
host = sdiodev->func[fn]->card->host; host = sdiodev->func[fn]->card->host;
func_blk_sz = sdiodev->func[fn]->cur_blksize; func_blk_sz = sdiodev->func[fn]->cur_blksize;
/* Blocks per command is limited by host count, host transfer /* Blocks per command is limited by host count, host transfer
...@@ -370,13 +407,15 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, ...@@ -370,13 +407,15 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
max_req_sz = min_t(unsigned int, host->max_req_size, max_req_sz = min_t(unsigned int, host->max_req_size,
max_blks * func_blk_sz); max_blks * func_blk_sz);
max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC); max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC);
max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen); max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen);
seg_sz = pktlist->qlen; seg_sz = target_list->qlen;
pkt_offset = 0; pkt_offset = 0;
pkt_next = pktlist->next; pkt_next = target_list->next;
if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) {
return -ENOMEM; ret = -ENOMEM;
goto exit;
}
while (seg_sz) { while (seg_sz) {
req_sz = 0; req_sz = 0;
...@@ -386,7 +425,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, ...@@ -386,7 +425,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
memset(&mmc_dat, 0, sizeof(struct mmc_data)); memset(&mmc_dat, 0, sizeof(struct mmc_data));
sgl = st.sgl; sgl = st.sgl;
/* prep sg table */ /* prep sg table */
while (pkt_next != (struct sk_buff *)pktlist) { while (pkt_next != (struct sk_buff *)target_list) {
pkt_data = pkt_next->data + pkt_offset; pkt_data = pkt_next->data + pkt_offset;
sg_data_sz = pkt_next->len - pkt_offset; sg_data_sz = pkt_next->len - pkt_offset;
if (sg_data_sz > host->max_seg_size) if (sg_data_sz > host->max_seg_size)
...@@ -413,8 +452,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, ...@@ -413,8 +452,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
if (req_sz % func_blk_sz != 0) { if (req_sz % func_blk_sz != 0) {
brcmf_err("sg request length %u is not %u aligned\n", brcmf_err("sg request length %u is not %u aligned\n",
req_sz, func_blk_sz); req_sz, func_blk_sz);
sg_free_table(&st); ret = -ENOTBLK;
return -ENOTBLK; goto exit;
} }
mmc_dat.sg = st.sgl; mmc_dat.sg = st.sgl;
mmc_dat.sg_len = sg_cnt; mmc_dat.sg_len = sg_cnt;
...@@ -447,35 +486,36 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, ...@@ -447,35 +486,36 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
} }
} }
sg_free_table(&st); if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
local_pkt_next = local_list.next;
return ret; orig_offset = 0;
} skb_queue_walk(pktlist, pkt_next) {
dst_offset = 0;
static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, do {
uint flags, uint width, u32 *addr) req_sz = local_pkt_next->len - orig_offset;
{ req_sz = min_t(uint, pkt_next->len - dst_offset,
uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; req_sz);
int err = 0; orig_data = local_pkt_next->data + orig_offset;
dst_data = pkt_next->data + dst_offset;
/* Async not implemented yet */ memcpy(dst_data, orig_data, req_sz);
if (flags & SDIO_REQ_ASYNC) orig_offset += req_sz;
return -ENOTSUPP; dst_offset += req_sz;
if (orig_offset == local_pkt_next->len) {
if (bar0 != sdiodev->sbwad) { orig_offset = 0;
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); local_pkt_next = local_pkt_next->next;
if (err) }
return err; if (dst_offset == pkt_next->len)
break;
sdiodev->sbwad = bar0; } while (!skb_queue_empty(&local_list));
}
} }
*addr &= SBSDIO_SB_OFT_ADDR_MASK; exit:
sg_free_table(&st);
if (width == 4) while ((pkt_next = __skb_dequeue(&local_list)) != NULL)
*addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; brcmu_pkt_buf_free_skb(pkt_next);
return 0; return ret;
} }
int int
...@@ -512,7 +552,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -512,7 +552,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
fn, addr, pkt->len); fn, addr, pkt->len);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); err = brcmf_sdio_addrprep(sdiodev, width, &addr);
if (err) if (err)
goto done; goto done;
...@@ -536,7 +576,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -536,7 +576,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
fn, addr, pktq->qlen); fn, addr, pktq->qlen);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); err = brcmf_sdio_addrprep(sdiodev, width, &addr);
if (err) if (err)
goto done; goto done;
...@@ -574,37 +614,20 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -574,37 +614,20 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff *pkt) uint flags, struct sk_buff *pkt)
{ {
uint width; uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0; int err = 0;
struct sk_buff_head pkt_list; struct sk_buff_head pkt_list;
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len); fn, addr, pkt->len);
/* Async not implemented yet */
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
if (bar0 != sdiodev->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
goto done;
sdiodev->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
if (width == 4) brcmf_sdio_addrprep(sdiodev, width, &addr);
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
skb_queue_head_init(&pkt_list); skb_queue_head_init(&pkt_list);
skb_queue_tail(&pkt_list, pkt); skb_queue_tail(&pkt_list, pkt);
err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list); err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list);
skb_dequeue_tail(&pkt_list); skb_dequeue_tail(&pkt_list);
done:
return err; return err;
} }
......
...@@ -281,8 +281,6 @@ void brcmf_txflowblock(struct device *dev, bool state) ...@@ -281,8 +281,6 @@ void brcmf_txflowblock(struct device *dev, bool state)
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
{ {
unsigned char *eth;
uint len;
struct sk_buff *skb, *pnext; struct sk_buff *skb, *pnext;
struct brcmf_if *ifp; struct brcmf_if *ifp;
struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_bus *bus_if = dev_get_drvdata(dev);
...@@ -306,33 +304,12 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) ...@@ -306,33 +304,12 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
continue; continue;
} }
/* Get the protocol, maintain skb around eth_type_trans()
* The main reason for this hack is for the limitation of
* Linux 2.4 where 'eth_type_trans' uses the
* 'net->hard_header_len'
* to perform skb_pull inside vs ETH_HLEN. Since to avoid
* coping of the packet coming from the network stack to add
* BDC, Hardware header etc, during network interface
* registration
* we set the 'net->hard_header_len' to ETH_HLEN + extra space
* required
* for BDC, Hardware header etc. and not just the ETH_HLEN
*/
eth = skb->data;
len = skb->len;
skb->dev = ifp->ndev; skb->dev = ifp->ndev;
skb->protocol = eth_type_trans(skb, skb->dev); skb->protocol = eth_type_trans(skb, skb->dev);
if (skb->pkt_type == PACKET_MULTICAST) if (skb->pkt_type == PACKET_MULTICAST)
ifp->stats.multicast++; ifp->stats.multicast++;
skb->data = eth;
skb->len = len;
/* Strip header, count, deliver upward */
skb_pull(skb, ETH_HLEN);
/* Process special event packets */ /* Process special event packets */
brcmf_fweh_process_skb(drvr, skb); brcmf_fweh_process_skb(drvr, skb);
...@@ -348,10 +325,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) ...@@ -348,10 +325,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
netif_rx(skb); netif_rx(skb);
else else
/* If the receive is not processed inside an ISR, /* If the receive is not processed inside an ISR,
* the softirqd must be woken explicitly to service * the softirqd must be woken explicitly to service the
* the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled * NET_RX_SOFTIRQ. This is handled by netif_rx_ni().
* by netif_rx_ni(), but in earlier kernels, we need
* to do it manually.
*/ */
netif_rx_ni(skb); netif_rx_ni(skb);
} }
......
...@@ -796,9 +796,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) ...@@ -796,9 +796,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
u8 fillers; u8 fillers;
__le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u (%u), pkttag=0x%08X, hslot=%d\n", brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n",
entry->ea, entry->interface_id, entry->name, brcmf_skb_if_flags_get_field(skb, INDEX),
brcmf_skb_if_flags_get_field(skb, INDEX),
le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff); le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff);
if (entry->send_tim_signal) if (entry->send_tim_signal)
data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
...@@ -822,8 +821,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) ...@@ -822,8 +821,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
wlh[2] = entry->mac_handle; wlh[2] = entry->mac_handle;
wlh[3] = entry->traffic_pending_bmp; wlh[3] = entry->traffic_pending_bmp;
brcmf_dbg(TRACE, "adding TIM info: %02X:%02X:%02X:%02X\n", brcmf_dbg(TRACE, "adding TIM info: handle %d bmp 0x%X\n",
wlh[0], wlh[1], wlh[2], wlh[3]); entry->mac_handle, entry->traffic_pending_bmp);
wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2; wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2;
entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
} }
...@@ -906,10 +905,26 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) ...@@ -906,10 +905,26 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
return 0; return 0;
} }
/* using macro so sparse checking does not complain
* about locking imbalance.
*/
#define brcmf_fws_lock(drvr, flags) \
do { \
flags = 0; \
spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
} while (0)
/* using macro so sparse checking does not complain
* about locking imbalance.
*/
#define brcmf_fws_unlock(drvr, flags) \
spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
static static
int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
{ {
struct brcmf_fws_mac_descriptor *entry, *existing; struct brcmf_fws_mac_descriptor *entry, *existing;
ulong flags;
u8 mac_handle; u8 mac_handle;
u8 ifidx; u8 ifidx;
u8 *addr; u8 *addr;
...@@ -923,8 +938,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) ...@@ -923,8 +938,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
if (entry->occupied) { if (entry->occupied) {
brcmf_dbg(TRACE, "deleting %s mac %pM\n", brcmf_dbg(TRACE, "deleting %s mac %pM\n",
entry->name, addr); entry->name, addr);
brcmf_fws_lock(fws->drvr, flags);
brcmf_fws_macdesc_cleanup(fws, entry, -1); brcmf_fws_macdesc_cleanup(fws, entry, -1);
brcmf_fws_macdesc_deinit(entry); brcmf_fws_macdesc_deinit(entry);
brcmf_fws_unlock(fws->drvr, flags);
} else } else
fws->stats.mac_update_failed++; fws->stats.mac_update_failed++;
return 0; return 0;
...@@ -933,11 +950,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) ...@@ -933,11 +950,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
existing = brcmf_fws_macdesc_lookup(fws, addr); existing = brcmf_fws_macdesc_lookup(fws, addr);
if (IS_ERR(existing)) { if (IS_ERR(existing)) {
if (!entry->occupied) { if (!entry->occupied) {
brcmf_fws_lock(fws->drvr, flags);
entry->mac_handle = mac_handle; entry->mac_handle = mac_handle;
brcmf_fws_macdesc_init(entry, addr, ifidx); brcmf_fws_macdesc_init(entry, addr, ifidx);
brcmf_fws_macdesc_set_name(fws, entry); brcmf_fws_macdesc_set_name(fws, entry);
brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
BRCMF_FWS_PSQ_LEN); BRCMF_FWS_PSQ_LEN);
brcmf_fws_unlock(fws->drvr, flags);
brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr); brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
} else { } else {
fws->stats.mac_update_failed++; fws->stats.mac_update_failed++;
...@@ -945,11 +964,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) ...@@ -945,11 +964,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
} else { } else {
if (entry != existing) { if (entry != existing) {
brcmf_dbg(TRACE, "copy mac %s\n", existing->name); brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
brcmf_fws_lock(fws->drvr, flags);
memcpy(entry, existing, memcpy(entry, existing,
offsetof(struct brcmf_fws_mac_descriptor, psq)); offsetof(struct brcmf_fws_mac_descriptor, psq));
entry->mac_handle = mac_handle; entry->mac_handle = mac_handle;
brcmf_fws_macdesc_deinit(existing); brcmf_fws_macdesc_deinit(existing);
brcmf_fws_macdesc_set_name(fws, entry); brcmf_fws_macdesc_set_name(fws, entry);
brcmf_fws_unlock(fws->drvr, flags);
brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name, brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
addr); addr);
} else { } else {
...@@ -965,7 +986,9 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, ...@@ -965,7 +986,9 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
u8 type, u8 *data) u8 type, u8 *data)
{ {
struct brcmf_fws_mac_descriptor *entry; struct brcmf_fws_mac_descriptor *entry;
ulong flags;
u8 mac_handle; u8 mac_handle;
int ret;
mac_handle = data[0]; mac_handle = data[0];
entry = &fws->desc.nodes[mac_handle & 0x1F]; entry = &fws->desc.nodes[mac_handle & 0x1F];
...@@ -973,26 +996,30 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, ...@@ -973,26 +996,30 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
fws->stats.mac_ps_update_failed++; fws->stats.mac_ps_update_failed++;
return -ESRCH; return -ESRCH;
} }
brcmf_fws_lock(fws->drvr, flags);
/* a state update should wipe old credits */ /* a state update should wipe old credits */
entry->requested_credit = 0; entry->requested_credit = 0;
entry->requested_packet = 0; entry->requested_packet = 0;
if (type == BRCMF_FWS_TYPE_MAC_OPEN) { if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
entry->state = BRCMF_FWS_STATE_OPEN; entry->state = BRCMF_FWS_STATE_OPEN;
return BRCMF_FWS_RET_OK_SCHEDULE; ret = BRCMF_FWS_RET_OK_SCHEDULE;
} else { } else {
entry->state = BRCMF_FWS_STATE_CLOSE; entry->state = BRCMF_FWS_STATE_CLOSE;
brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
} }
return BRCMF_FWS_RET_OK_NOSCHEDULE; brcmf_fws_unlock(fws->drvr, flags);
return ret;
} }
static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
u8 type, u8 *data) u8 type, u8 *data)
{ {
struct brcmf_fws_mac_descriptor *entry; struct brcmf_fws_mac_descriptor *entry;
ulong flags;
u8 ifidx; u8 ifidx;
int ret; int ret;
...@@ -1011,17 +1038,24 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, ...@@ -1011,17 +1038,24 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type, brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
entry->name); entry->name);
brcmf_fws_lock(fws->drvr, flags);
switch (type) { switch (type) {
case BRCMF_FWS_TYPE_INTERFACE_OPEN: case BRCMF_FWS_TYPE_INTERFACE_OPEN:
entry->state = BRCMF_FWS_STATE_OPEN; entry->state = BRCMF_FWS_STATE_OPEN;
return BRCMF_FWS_RET_OK_SCHEDULE; ret = BRCMF_FWS_RET_OK_SCHEDULE;
break;
case BRCMF_FWS_TYPE_INTERFACE_CLOSE: case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
entry->state = BRCMF_FWS_STATE_CLOSE; entry->state = BRCMF_FWS_STATE_CLOSE;
return BRCMF_FWS_RET_OK_NOSCHEDULE; ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; brcmf_fws_unlock(fws->drvr, flags);
goto fail;
} }
brcmf_fws_unlock(fws->drvr, flags);
return ret;
fail: fail:
fws->stats.if_update_failed++; fws->stats.if_update_failed++;
return ret; return ret;
...@@ -1031,6 +1065,7 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, ...@@ -1031,6 +1065,7 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
u8 *data) u8 *data)
{ {
struct brcmf_fws_mac_descriptor *entry; struct brcmf_fws_mac_descriptor *entry;
ulong flags;
entry = &fws->desc.nodes[data[1] & 0x1F]; entry = &fws->desc.nodes[data[1] & 0x1F];
if (!entry->occupied) { if (!entry->occupied) {
...@@ -1044,12 +1079,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, ...@@ -1044,12 +1079,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n", brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
brcmf_fws_get_tlv_name(type), type, entry->name, brcmf_fws_get_tlv_name(type), type, entry->name,
data[0], data[2]); data[0], data[2]);
brcmf_fws_lock(fws->drvr, flags);
if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
entry->requested_credit = data[0]; entry->requested_credit = data[0];
else else
entry->requested_packet = data[0]; entry->requested_packet = data[0];
entry->ac_bitmap = data[2]; entry->ac_bitmap = data[2];
brcmf_fws_unlock(fws->drvr, flags);
return BRCMF_FWS_RET_OK_SCHEDULE; return BRCMF_FWS_RET_OK_SCHEDULE;
} }
...@@ -1346,6 +1383,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, ...@@ -1346,6 +1383,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
u8 *data) u8 *data)
{ {
ulong flags;
int i; int i;
if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
...@@ -1354,16 +1392,19 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, ...@@ -1354,16 +1392,19 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
} }
brcmf_dbg(DATA, "enter: data %pM\n", data); brcmf_dbg(DATA, "enter: data %pM\n", data);
brcmf_fws_lock(fws->drvr, flags);
for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
brcmf_fws_return_credits(fws, i, data[i]); brcmf_fws_return_credits(fws, i, data[i]);
brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map, brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
fws->fifo_delay_map); fws->fifo_delay_map);
brcmf_fws_unlock(fws->drvr, flags);
return BRCMF_FWS_RET_OK_SCHEDULE; return BRCMF_FWS_RET_OK_SCHEDULE;
} }
static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
{ {
ulong lflags;
__le32 status_le; __le32 status_le;
u32 status; u32 status;
u32 hslot; u32 hslot;
...@@ -1377,7 +1418,10 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) ...@@ -1377,7 +1418,10 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
hslot = brcmf_txstatus_get_field(status, HSLOT); hslot = brcmf_txstatus_get_field(status, HSLOT);
genbit = brcmf_txstatus_get_field(status, GENERATION); genbit = brcmf_txstatus_get_field(status, GENERATION);
return brcmf_fws_txs_process(fws, flags, hslot, genbit); brcmf_fws_lock(fws->drvr, lflags);
brcmf_fws_txs_process(fws, flags, hslot, genbit);
brcmf_fws_unlock(fws->drvr, lflags);
return BRCMF_FWS_RET_OK_NOSCHEDULE;
} }
static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
...@@ -1390,21 +1434,6 @@ static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) ...@@ -1390,21 +1434,6 @@ static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
return 0; return 0;
} }
/* using macro so sparse checking does not complain
* about locking imbalance.
*/
#define brcmf_fws_lock(drvr, flags) \
do { \
flags = 0; \
spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
} while (0)
/* using macro so sparse checking does not complain
* about locking imbalance.
*/
#define brcmf_fws_unlock(drvr, flags) \
spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, const struct brcmf_event_msg *e,
void *data) void *data)
...@@ -1455,7 +1484,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, ...@@ -1455,7 +1484,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct brcmf_fws_info *fws = drvr->fws; struct brcmf_fws_info *fws = drvr->fws;
ulong flags;
u8 *signal_data; u8 *signal_data;
s16 data_len; s16 data_len;
u8 type; u8 type;
...@@ -1475,9 +1503,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, ...@@ -1475,9 +1503,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
return 0; return 0;
} }
/* lock during tlv parsing */
brcmf_fws_lock(drvr, flags);
fws->stats.header_pulls++; fws->stats.header_pulls++;
data_len = signal_len; data_len = signal_len;
signal_data = skb->data; signal_data = skb->data;
...@@ -1571,25 +1596,17 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, ...@@ -1571,25 +1596,17 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
if (skb->len == 0) if (skb->len == 0)
fws->stats.header_only_pkt++; fws->stats.header_only_pkt++;
brcmf_fws_unlock(drvr, flags);
return 0; return 0;
} }
static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
struct sk_buff *p) struct sk_buff *p)
{ {
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
struct brcmf_fws_mac_descriptor *entry = skcb->mac; struct brcmf_fws_mac_descriptor *entry = skcb->mac;
int rc = 0;
bool first_time;
int hslot = BRCMF_FWS_HANGER_MAXITEMS;
u8 free_ctr;
u8 flags; u8 flags;
first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED;
brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
if (brcmf_skb_if_flags_get_field(p, REQUESTED)) { if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
...@@ -1600,80 +1617,36 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, ...@@ -1600,80 +1617,36 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
} }
brcmf_skb_htod_tag_set_field(p, FLAGS, flags); brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
if (first_time) { brcmf_fws_hdrpush(fws, p);
/* obtaining free slot may fail, but that will be caught
* by the hanger push. This assures the packet has a BDC
* header upon return.
*/
hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
free_ctr = entry->seq[fifo];
brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr);
rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
if (rc)
brcmf_err("hanger push failed: rc=%d\n", rc);
}
if (rc == 0)
brcmf_fws_hdrpush(fws, p);
return rc;
} }
static void static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb, int fifo)
struct sk_buff *skb, int fifo)
{ {
/*
put the packet back to the head of queue
- suppressed packet goes back to suppress sub-queue
- pull out the header, if new or delayed packet
Note: hslot is used only when header removal is done.
*/
struct brcmf_fws_mac_descriptor *entry; struct brcmf_fws_mac_descriptor *entry;
enum brcmf_fws_skb_state state;
struct sk_buff *pktout; struct sk_buff *pktout;
int qidx, hslot;
int rc = 0; int rc = 0;
int hslot;
state = brcmf_skbcb(skb)->state;
entry = brcmf_skbcb(skb)->mac; entry = brcmf_skbcb(skb)->mac;
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); if (entry->occupied) {
qidx = 2 * fifo;
if (entry != NULL) { if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { qidx++;
/* wl-header is saved for suppressed packets */
pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1, pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
skb); if (pktout == NULL) {
if (pktout == NULL) { brcmf_err("%s queue %d full\n", entry->name, qidx);
brcmf_err("suppress queue full\n"); rc = -ENOSPC;
rc = -ENOSPC;
}
} else {
/* delay-q packets are going to delay-q */
pktout = brcmu_pktq_penq_head(&entry->psq,
2 * fifo, skb);
if (pktout == NULL) {
brcmf_err("delay queue full\n");
rc = -ENOSPC;
}
/* free the hanger slot */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout,
true);
/* decrement sequence count */
entry->seq[fifo]--;
} }
} else { } else {
brcmf_err("no mac entry linked\n"); brcmf_err("%s entry removed\n", entry->name);
rc = -ENOENT; rc = -ENOENT;
} }
if (rc) { if (rc) {
fws->stats.rollback_failed++; fws->stats.rollback_failed++;
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
hslot, 0); hslot, 0);
} else { } else {
...@@ -1707,37 +1680,6 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) ...@@ -1707,37 +1680,6 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
return -ENAVAIL; return -ENAVAIL;
} }
static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
struct sk_buff *skb)
{
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
int *credit = &fws->fifo_credit[fifo];
if (fifo != BRCMF_FWS_FIFO_AC_BE)
fws->borrow_defer_timestamp = jiffies +
BRCMF_FWS_BORROW_DEFER_PERIOD;
if (!(*credit)) {
/* Try to borrow a credit from other queue */
if (fifo != BRCMF_FWS_FIFO_AC_BE ||
(brcmf_fws_borrow_credit(fws) != 0)) {
brcmf_dbg(DATA, "ac=%d, credits depleted\n", fifo);
return -ENAVAIL;
}
} else {
(*credit)--;
if (!(*credit))
fws->fifo_credit_map &= ~(1 << fifo);
}
brcmf_fws_macdesc_use_req_credit(entry, skb);
brcmf_dbg(DATA, "ac=%d, credits=%02d:%02d:%02d:%02d\n", fifo,
fws->fifo_credit[0], fws->fifo_credit[1],
fws->fifo_credit[2], fws->fifo_credit[3]);
return 0;
}
static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -1751,15 +1693,10 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, ...@@ -1751,15 +1693,10 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
if (IS_ERR(entry)) if (IS_ERR(entry))
return PTR_ERR(entry); return PTR_ERR(entry);
rc = brcmf_fws_precommit_skb(fws, fifo, skb); brcmf_fws_precommit_skb(fws, fifo, skb);
if (rc < 0) {
fws->stats.generic_error++;
goto rollback;
}
brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags,
skcb->htod);
rc = brcmf_bus_txdata(bus, skb); rc = brcmf_bus_txdata(bus, skb);
brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
skcb->if_flags, skcb->htod, rc);
if (rc < 0) { if (rc < 0) {
brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
goto rollback; goto rollback;
...@@ -1768,7 +1705,6 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, ...@@ -1768,7 +1705,6 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
entry->transit_count++; entry->transit_count++;
if (entry->suppressed) if (entry->suppressed)
entry->suppr_transit_count++; entry->suppr_transit_count++;
entry->seq[fifo]++;
fws->stats.pkt2bus++; fws->stats.pkt2bus++;
fws->stats.send_pkts[fifo]++; fws->stats.send_pkts[fifo]++;
if (brcmf_skb_if_flags_get_field(skb, REQUESTED)) if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
...@@ -1781,6 +1717,24 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, ...@@ -1781,6 +1717,24 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
return rc; return rc;
} }
static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
int fifo)
{
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
int rc, hslot;
hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
if (!rc)
skcb->mac->seq[fifo]++;
else
fws->stats.generic_error++;
return rc;
}
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
{ {
struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pub *drvr = ifp->drvr;
...@@ -1809,33 +1763,25 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) ...@@ -1809,33 +1763,25 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
/* set control buffer information */ /* set control buffer information */
skcb->if_flags = 0; skcb->if_flags = 0;
skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
skcb->state = BRCMF_FWS_SKBSTATE_NEW; skcb->state = BRCMF_FWS_SKBSTATE_NEW;
brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
if (!multicast) if (!multicast)
fifo = brcmf_fws_prio2fifo[skb->priority]; fifo = brcmf_fws_prio2fifo[skb->priority];
brcmf_fws_lock(drvr, flags);
if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
fws->borrow_defer_timestamp = jiffies +
BRCMF_FWS_BORROW_DEFER_PERIOD;
skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name, brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
eh->h_dest, multicast, fifo); eh->h_dest, multicast, fifo);
if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
brcmf_fws_lock(drvr, flags);
/* multicast credit support is conditional, setting
* flag to false to assure credit is consumed below.
*/
if (fws->bcmc_credit_check)
multicast = false;
if (skcb->mac->suppressed ||
fws->bus_flow_blocked ||
brcmf_fws_macdesc_closed(fws, skcb->mac, fifo) ||
brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
(!multicast &&
brcmf_fws_consume_credit(fws, fifo, skb) < 0)) {
/* enqueue the packet in delayQ */
drvr->fws->fifo_delay_map |= 1 << fifo;
brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
brcmf_fws_schedule_deq(fws);
} else { } else {
brcmf_fws_commit_skb(fws, fifo, skb); brcmf_err("drop skb: no hanger slot\n");
brcmu_pkt_buf_free_skb(skb);
} }
brcmf_fws_unlock(drvr, flags); brcmf_fws_unlock(drvr, flags);
return 0; return 0;
...@@ -1895,7 +1841,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) ...@@ -1895,7 +1841,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
brcmf_fws_lock(fws->drvr, flags); brcmf_fws_lock(fws->drvr, flags);
for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked; for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
fifo--) { fifo--) {
while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
(fifo == BRCMF_FWS_FIFO_BCMC))) { (fifo == BRCMF_FWS_FIFO_BCMC))) {
......
...@@ -229,8 +229,6 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -229,8 +229,6 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
#define SDIO_REQ_4BYTE 0x1 #define SDIO_REQ_4BYTE 0x1
/* Fixed address (FIFO) (vs. incrementing address) */ /* Fixed address (FIFO) (vs. incrementing address) */
#define SDIO_REQ_FIXED 0x2 #define SDIO_REQ_FIXED 0x2
/* Async request (vs. sync request) */
#define SDIO_REQ_ASYNC 0x4
/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). /* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
* rw: read or write (0/1) * rw: read or write (0/1)
...@@ -251,9 +249,6 @@ extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); ...@@ -251,9 +249,6 @@ extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
u32 address);
/* attach, return handler on success, NULL if failed. /* attach, return handler on success, NULL if failed.
* The handler shall be provided by all subsequent calls. No local cache * The handler shall be provided by all subsequent calls. No local cache
* cfghdl points to the starting address of pci device mapped memory * cfghdl points to the starting address of pci device mapped memory
......
...@@ -267,7 +267,7 @@ struct cw1200_common { ...@@ -267,7 +267,7 @@ struct cw1200_common {
struct delayed_work bss_loss_work; struct delayed_work bss_loss_work;
spinlock_t bss_loss_lock; /* Protect BSS loss state */ spinlock_t bss_loss_lock; /* Protect BSS loss state */
int bss_loss_state; int bss_loss_state;
int bss_loss_confirm_id; u32 bss_loss_confirm_id;
int delayed_link_loss; int delayed_link_loss;
struct work_struct bss_params_work; struct work_struct bss_params_work;
......
...@@ -61,7 +61,7 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, ...@@ -61,7 +61,7 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self,
void *dst, int count) void *dst, int count)
{ {
int ret, i; int ret, i;
uint16_t regaddr; u16 regaddr;
struct spi_message m; struct spi_message m;
struct spi_transfer t_addr = { struct spi_transfer t_addr = {
...@@ -76,15 +76,18 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, ...@@ -76,15 +76,18 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self,
regaddr = (SDIO_TO_SPI_ADDR(addr))<<12; regaddr = (SDIO_TO_SPI_ADDR(addr))<<12;
regaddr |= SET_READ; regaddr |= SET_READ;
regaddr |= (count>>1); regaddr |= (count>>1);
regaddr = cpu_to_le16(regaddr);
#ifdef SPI_DEBUG #ifdef SPI_DEBUG
pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, regaddr);
le16_to_cpu(regaddr));
#endif #endif
/* Header is LE16 */
regaddr = cpu_to_le16(regaddr);
/* We have to byteswap if the SPI bus is limited to 8b operation
or we are running on a Big Endian system
*/
#if defined(__LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN)
/* We have to byteswap if the SPI bus is limited to 8b operation */
if (self->func->bits_per_word == 8) if (self->func->bits_per_word == 8)
#endif #endif
regaddr = swab16(regaddr); regaddr = swab16(regaddr);
...@@ -104,8 +107,10 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, ...@@ -104,8 +107,10 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self,
printk("\n"); printk("\n");
#endif #endif
/* We have to byteswap if the SPI bus is limited to 8b operation
or we are running on a Big Endian system
*/
#if defined(__LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN)
/* We have to byteswap if the SPI bus is limited to 8b operation */
if (self->func->bits_per_word == 8) if (self->func->bits_per_word == 8)
#endif #endif
{ {
...@@ -122,7 +127,7 @@ static int cw1200_spi_memcpy_toio(struct hwbus_priv *self, ...@@ -122,7 +127,7 @@ static int cw1200_spi_memcpy_toio(struct hwbus_priv *self,
const void *src, int count) const void *src, int count)
{ {
int rval, i; int rval, i;
uint16_t regaddr; u16 regaddr;
struct spi_transfer t_addr = { struct spi_transfer t_addr = {
.tx_buf = &regaddr, .tx_buf = &regaddr,
.len = sizeof(regaddr), .len = sizeof(regaddr),
...@@ -136,20 +141,23 @@ static int cw1200_spi_memcpy_toio(struct hwbus_priv *self, ...@@ -136,20 +141,23 @@ static int cw1200_spi_memcpy_toio(struct hwbus_priv *self,
regaddr = (SDIO_TO_SPI_ADDR(addr))<<12; regaddr = (SDIO_TO_SPI_ADDR(addr))<<12;
regaddr &= SET_WRITE; regaddr &= SET_WRITE;
regaddr |= (count>>1); regaddr |= (count>>1);
regaddr = cpu_to_le16(regaddr);
#ifdef SPI_DEBUG #ifdef SPI_DEBUG
pr_info("WRITE: %04d to 0x%02x (%04x)\n", count, addr, pr_info("WRITE: %04d to 0x%02x (%04x)\n", count, addr, regaddr);
le16_to_cpu(regaddr));
#endif #endif
/* Header is LE16 */
regaddr = cpu_to_le16(regaddr);
/* We have to byteswap if the SPI bus is limited to 8b operation
or we are running on a Big Endian system
*/
#if defined(__LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN)
/* We have to byteswap if the SPI bus is limited to 8b operation */
if (self->func->bits_per_word == 8) if (self->func->bits_per_word == 8)
#endif #endif
{ {
uint16_t *buf = (uint16_t *)src; uint16_t *buf = (uint16_t *)src;
regaddr = swab16(regaddr); regaddr = swab16(regaddr);
for (i = 0; i < ((count + 1) >> 1); i++) for (i = 0; i < ((count + 1) >> 1); i++)
buf[i] = swab16(buf[i]); buf[i] = swab16(buf[i]);
} }
......
...@@ -69,31 +69,33 @@ static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr, ...@@ -69,31 +69,33 @@ static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr,
static inline int __cw1200_reg_read_32(struct cw1200_common *priv, static inline int __cw1200_reg_read_32(struct cw1200_common *priv,
u16 addr, u32 *val) u16 addr, u32 *val)
{ {
int i = __cw1200_reg_read(priv, addr, val, sizeof(*val), 0); __le32 tmp;
*val = le32_to_cpu(*val); int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
*val = le32_to_cpu(tmp);
return i; return i;
} }
static inline int __cw1200_reg_write_32(struct cw1200_common *priv, static inline int __cw1200_reg_write_32(struct cw1200_common *priv,
u16 addr, u32 val) u16 addr, u32 val)
{ {
val = cpu_to_le32(val); __le32 tmp = cpu_to_le32(val);
return __cw1200_reg_write(priv, addr, &val, sizeof(val), 0); return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
} }
static inline int __cw1200_reg_read_16(struct cw1200_common *priv, static inline int __cw1200_reg_read_16(struct cw1200_common *priv,
u16 addr, u16 *val) u16 addr, u16 *val)
{ {
int i = __cw1200_reg_read(priv, addr, val, sizeof(*val), 0); __le16 tmp;
*val = le16_to_cpu(*val); int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
*val = le16_to_cpu(tmp);
return i; return i;
} }
static inline int __cw1200_reg_write_16(struct cw1200_common *priv, static inline int __cw1200_reg_write_16(struct cw1200_common *priv,
u16 addr, u16 val) u16 addr, u16 val)
{ {
val = cpu_to_le16(val); __le16 tmp = cpu_to_le16(val);
return __cw1200_reg_write(priv, addr, &val, sizeof(val), 0); return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
} }
int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf, int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf,
......
...@@ -169,35 +169,34 @@ int cw1200_reg_write(struct cw1200_common *priv, u16 addr, ...@@ -169,35 +169,34 @@ int cw1200_reg_write(struct cw1200_common *priv, u16 addr,
static inline int cw1200_reg_read_16(struct cw1200_common *priv, static inline int cw1200_reg_read_16(struct cw1200_common *priv,
u16 addr, u16 *val) u16 addr, u16 *val)
{ {
u32 tmp; __le32 tmp;
int i; int i;
i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp)); i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp));
tmp = le32_to_cpu(tmp); *val = le32_to_cpu(tmp) & 0xfffff;
*val = tmp & 0xffff;
return i; return i;
} }
static inline int cw1200_reg_write_16(struct cw1200_common *priv, static inline int cw1200_reg_write_16(struct cw1200_common *priv,
u16 addr, u16 val) u16 addr, u16 val)
{ {
u32 tmp = val; __le32 tmp = cpu_to_le32((u32)val);
tmp = cpu_to_le32(tmp);
return cw1200_reg_write(priv, addr, &tmp, sizeof(tmp)); return cw1200_reg_write(priv, addr, &tmp, sizeof(tmp));
} }
static inline int cw1200_reg_read_32(struct cw1200_common *priv, static inline int cw1200_reg_read_32(struct cw1200_common *priv,
u16 addr, u32 *val) u16 addr, u32 *val)
{ {
int i = cw1200_reg_read(priv, addr, val, sizeof(*val)); __le32 tmp;
*val = le32_to_cpu(*val); int i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp));
*val = le32_to_cpu(tmp);
return i; return i;
} }
static inline int cw1200_reg_write_32(struct cw1200_common *priv, static inline int cw1200_reg_write_32(struct cw1200_common *priv,
u16 addr, u32 val) u16 addr, u32 val)
{ {
val = cpu_to_le32(val); __le32 tmp = cpu_to_le32(val);
return cw1200_reg_write(priv, addr, &val, sizeof(val)); return cw1200_reg_write(priv, addr, &tmp, sizeof(val));
} }
int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf,
...@@ -224,22 +223,24 @@ static inline int cw1200_ahb_read(struct cw1200_common *priv, u32 addr, ...@@ -224,22 +223,24 @@ static inline int cw1200_ahb_read(struct cw1200_common *priv, u32 addr,
static inline int cw1200_apb_read_32(struct cw1200_common *priv, static inline int cw1200_apb_read_32(struct cw1200_common *priv,
u32 addr, u32 *val) u32 addr, u32 *val)
{ {
int i = cw1200_apb_read(priv, addr, val, sizeof(*val)); __le32 tmp;
*val = le32_to_cpu(*val); int i = cw1200_apb_read(priv, addr, &tmp, sizeof(tmp));
*val = le32_to_cpu(tmp);
return i; return i;
} }
static inline int cw1200_apb_write_32(struct cw1200_common *priv, static inline int cw1200_apb_write_32(struct cw1200_common *priv,
u32 addr, u32 val) u32 addr, u32 val)
{ {
val = cpu_to_le32(val); __le32 tmp = cpu_to_le32(val);
return cw1200_apb_write(priv, addr, &val, sizeof(val)); return cw1200_apb_write(priv, addr, &tmp, sizeof(val));
} }
static inline int cw1200_ahb_read_32(struct cw1200_common *priv, static inline int cw1200_ahb_read_32(struct cw1200_common *priv,
u32 addr, u32 *val) u32 addr, u32 *val)
{ {
int i = cw1200_ahb_read(priv, addr, val, sizeof(*val)); __le32 tmp;
*val = le32_to_cpu(*val); int i = cw1200_ahb_read(priv, addr, &tmp, sizeof(tmp));
*val = le32_to_cpu(tmp);
return i; return i;
} }
......
...@@ -238,8 +238,8 @@ static const struct ieee80211_ops cw1200_ops = { ...@@ -238,8 +238,8 @@ static const struct ieee80211_ops cw1200_ops = {
/*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel, */ /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel, */
}; };
int cw1200_ba_rx_tids = -1; static int cw1200_ba_rx_tids = -1;
int cw1200_ba_tx_tids = -1; static int cw1200_ba_tx_tids = -1;
module_param(cw1200_ba_rx_tids, int, 0644); module_param(cw1200_ba_rx_tids, int, 0644);
module_param(cw1200_ba_tx_tids, int, 0644); module_param(cw1200_ba_tx_tids, int, 0644);
MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs"); MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
......
...@@ -355,7 +355,7 @@ int cw1200_queue_get(struct cw1200_queue *queue, ...@@ -355,7 +355,7 @@ int cw1200_queue_get(struct cw1200_queue *queue,
*tx = (struct wsm_tx *)item->skb->data; *tx = (struct wsm_tx *)item->skb->data;
*tx_info = IEEE80211_SKB_CB(item->skb); *tx_info = IEEE80211_SKB_CB(item->skb);
*txpriv = &item->txpriv; *txpriv = &item->txpriv;
(*tx)->packet_id = __cpu_to_le32(item->packet_id); (*tx)->packet_id = item->packet_id;
list_move_tail(&item->head, &queue->pending); list_move_tail(&item->head, &queue->pending);
++queue->num_pending; ++queue->num_pending;
--queue->link_map_cache[item->txpriv.link_id]; --queue->link_map_cache[item->txpriv.link_id];
......
...@@ -621,7 +621,7 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, ...@@ -621,7 +621,7 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
mutex_lock(&priv->conf_mutex); mutex_lock(&priv->conf_mutex);
if (queue < dev->queues) { if (queue < dev->queues) {
old_uapsd_flags = priv->uapsd_info.uapsd_flags; old_uapsd_flags = le16_to_cpu(priv->uapsd_info.uapsd_flags);
WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0); WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0);
ret = wsm_set_tx_queue_params(priv, ret = wsm_set_tx_queue_params(priv,
...@@ -645,7 +645,7 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, ...@@ -645,7 +645,7 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
ret = cw1200_set_uapsd_param(priv, &priv->edca); ret = cw1200_set_uapsd_param(priv, &priv->edca);
if (!ret && priv->setbssparams_done && if (!ret && priv->setbssparams_done &&
(priv->join_status == CW1200_JOIN_STATUS_STA) && (priv->join_status == CW1200_JOIN_STATUS_STA) &&
(old_uapsd_flags != priv->uapsd_info.uapsd_flags)) (old_uapsd_flags != le16_to_cpu(priv->uapsd_info.uapsd_flags)))
ret = cw1200_set_pm(priv, &priv->powersave_mode); ret = cw1200_set_pm(priv, &priv->powersave_mode);
} }
} else { } else {
...@@ -1089,18 +1089,18 @@ static int cw1200_parse_sdd_file(struct cw1200_common *priv) ...@@ -1089,18 +1089,18 @@ static int cw1200_parse_sdd_file(struct cw1200_common *priv)
ret = -1; ret = -1;
break; break;
} }
v = le16_to_cpu(*((u16 *)(p + 2))); v = le16_to_cpu(*((__le16 *)(p + 2)));
if (!v) /* non-zero means this is enabled */ if (!v) /* non-zero means this is enabled */
break; break;
v = le16_to_cpu(*((u16 *)(p + 4))); v = le16_to_cpu(*((__le16 *)(p + 4)));
priv->conf_listen_interval = (v >> 7) & 0x1F; priv->conf_listen_interval = (v >> 7) & 0x1F;
pr_debug("PTA found; Listen Interval %d\n", pr_debug("PTA found; Listen Interval %d\n",
priv->conf_listen_interval); priv->conf_listen_interval);
break; break;
} }
case SDD_REFERENCE_FREQUENCY_ELT_ID: { case SDD_REFERENCE_FREQUENCY_ELT_ID: {
u16 clk = le16_to_cpu(*((u16 *)(p + 2))); u16 clk = le16_to_cpu(*((__le16 *)(p + 2)));
if (clk != priv->hw_refclk) if (clk != priv->hw_refclk)
pr_warn("SDD file doesn't match configured refclk (%d vs %d)\n", pr_warn("SDD file doesn't match configured refclk (%d vs %d)\n",
clk, priv->hw_refclk); clk, priv->hw_refclk);
...@@ -1785,9 +1785,9 @@ static int cw1200_set_btcoexinfo(struct cw1200_common *priv) ...@@ -1785,9 +1785,9 @@ static int cw1200_set_btcoexinfo(struct cw1200_common *priv)
} else { } else {
pr_debug("[STA] STA has non ERP rates\n"); pr_debug("[STA] STA has non ERP rates\n");
/* B only mode */ /* B only mode */
arg.internalTxRate = (__ffs(priv->association_mode.basic_rate_set)); arg.internalTxRate = (__ffs(le32_to_cpu(priv->association_mode.basic_rate_set)));
} }
arg.nonErpInternalTxRate = (__ffs(priv->association_mode.basic_rate_set)); arg.nonErpInternalTxRate = (__ffs(le32_to_cpu(priv->association_mode.basic_rate_set)));
} else { } else {
/* P2P mode */ /* P2P mode */
arg.internalTxRate = (__ffs(priv->bss_params.operational_rate_set & ~0xF)); arg.internalTxRate = (__ffs(priv->bss_params.operational_rate_set & ~0xF));
...@@ -1908,7 +1908,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, ...@@ -1908,7 +1908,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
if (info->assoc || info->ibss_joined) { if (info->assoc || info->ibss_joined) {
struct ieee80211_sta *sta = NULL; struct ieee80211_sta *sta = NULL;
u32 val = 0; __le32 htprot = 0;
if (info->dtim_period) if (info->dtim_period)
priv->join_dtim_period = info->dtim_period; priv->join_dtim_period = info->dtim_period;
...@@ -1935,19 +1935,18 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, ...@@ -1935,19 +1935,18 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
/* Non Greenfield stations present */ /* Non Greenfield stations present */
if (priv->ht_info.operation_mode & if (priv->ht_info.operation_mode &
IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
val |= WSM_NON_GREENFIELD_STA_PRESENT; htprot |= cpu_to_le32(WSM_NON_GREENFIELD_STA_PRESENT);
/* Set HT protection method */ /* Set HT protection method */
val |= (priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) << 2; htprot |= cpu_to_le32((priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) << 2);
/* TODO: /* TODO:
* STBC_param.dual_cts * STBC_param.dual_cts
* STBC_param.LSIG_TXOP_FILL * STBC_param.LSIG_TXOP_FILL
*/ */
val = cpu_to_le32(val);
wsm_write_mib(priv, WSM_MIB_ID_SET_HT_PROTECTION, wsm_write_mib(priv, WSM_MIB_ID_SET_HT_PROTECTION,
&val, sizeof(val)); &htprot, sizeof(htprot));
priv->association_mode.greenfield = priv->association_mode.greenfield =
cw1200_ht_greenfield(&priv->ht_info); cw1200_ht_greenfield(&priv->ht_info);
......
...@@ -599,15 +599,15 @@ cw1200_tx_h_bt(struct cw1200_common *priv, ...@@ -599,15 +599,15 @@ cw1200_tx_h_bt(struct cw1200_common *priv,
} else if (ieee80211_is_data(t->hdr->frame_control)) { } else if (ieee80211_is_data(t->hdr->frame_control)) {
/* Skip LLC SNAP header (+6) */ /* Skip LLC SNAP header (+6) */
u8 *payload = &t->skb->data[t->hdrlen]; u8 *payload = &t->skb->data[t->hdrlen];
u16 *ethertype = (u16 *)&payload[6]; __be16 *ethertype = (__be16 *)&payload[6];
if (*ethertype == __be16_to_cpu(ETH_P_PAE)) if (be16_to_cpu(*ethertype) == ETH_P_PAE)
priority = WSM_EPTA_PRIORITY_EAPOL; priority = WSM_EPTA_PRIORITY_EAPOL;
} else if (ieee80211_is_assoc_req(t->hdr->frame_control) || } else if (ieee80211_is_assoc_req(t->hdr->frame_control) ||
ieee80211_is_reassoc_req(t->hdr->frame_control)) { ieee80211_is_reassoc_req(t->hdr->frame_control)) {
struct ieee80211_mgmt *mgt_frame = struct ieee80211_mgmt *mgt_frame =
(struct ieee80211_mgmt *)t->hdr; (struct ieee80211_mgmt *)t->hdr;
if (mgt_frame->u.assoc_req.listen_interval < if (le16_to_cpu(mgt_frame->u.assoc_req.listen_interval) <
priv->listen_interval) { priv->listen_interval) {
pr_debug("Modified Listen Interval to %d from %d\n", pr_debug("Modified Listen Interval to %d from %d\n",
priv->listen_interval, priv->listen_interval,
...@@ -615,8 +615,7 @@ cw1200_tx_h_bt(struct cw1200_common *priv, ...@@ -615,8 +615,7 @@ cw1200_tx_h_bt(struct cw1200_common *priv,
/* Replace listen interval derieved from /* Replace listen interval derieved from
* the one read from SDD * the one read from SDD
*/ */
mgt_frame->u.assoc_req.listen_interval = mgt_frame->u.assoc_req.listen_interval = cpu_to_le16(priv->listen_interval);
priv->listen_interval;
} }
} }
......
...@@ -42,19 +42,19 @@ ...@@ -42,19 +42,19 @@
(buf)->data += size; \ (buf)->data += size; \
} while (0) } while (0)
#define __WSM_GET(buf, type, cvt) \ #define __WSM_GET(buf, type, type2, cvt) \
({ \ ({ \
type val; \ type val; \
if ((buf)->data + sizeof(type) > (buf)->end) \ if ((buf)->data + sizeof(type) > (buf)->end) \
goto underflow; \ goto underflow; \
val = cvt(*(type *)(buf)->data); \ val = cvt(*(type2 *)(buf)->data); \
(buf)->data += sizeof(type); \ (buf)->data += sizeof(type); \
val; \ val; \
}) })
#define WSM_GET8(buf) __WSM_GET(buf, u8, (u8)) #define WSM_GET8(buf) __WSM_GET(buf, u8, u8, (u8))
#define WSM_GET16(buf) __WSM_GET(buf, u16, __le16_to_cpu) #define WSM_GET16(buf) __WSM_GET(buf, u16, __le16, __le16_to_cpu)
#define WSM_GET32(buf) __WSM_GET(buf, u32, __le32_to_cpu) #define WSM_GET32(buf) __WSM_GET(buf, u32, __le32, __le32_to_cpu)
#define WSM_PUT(buf, ptr, size) \ #define WSM_PUT(buf, ptr, size) \
do { \ do { \
...@@ -65,18 +65,18 @@ ...@@ -65,18 +65,18 @@
(buf)->data += size; \ (buf)->data += size; \
} while (0) } while (0)
#define __WSM_PUT(buf, val, type, cvt) \ #define __WSM_PUT(buf, val, type, type2, cvt) \
do { \ do { \
if ((buf)->data + sizeof(type) > (buf)->end) \ if ((buf)->data + sizeof(type) > (buf)->end) \
if (wsm_buf_reserve((buf), sizeof(type))) \ if (wsm_buf_reserve((buf), sizeof(type))) \
goto nomem; \ goto nomem; \
*(type *)(buf)->data = cvt(val); \ *(type2 *)(buf)->data = cvt(val); \
(buf)->data += sizeof(type); \ (buf)->data += sizeof(type); \
} while (0) } while (0)
#define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, (u8)) #define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, u8, (u8))
#define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __cpu_to_le16) #define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __le16, __cpu_to_le16)
#define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __cpu_to_le32) #define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __le32, __cpu_to_le32)
static void wsm_buf_reset(struct wsm_buf *buf); static void wsm_buf_reset(struct wsm_buf *buf);
static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size); static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size);
...@@ -931,8 +931,8 @@ static int wsm_event_indication(struct cw1200_common *priv, struct wsm_buf *buf) ...@@ -931,8 +931,8 @@ static int wsm_event_indication(struct cw1200_common *priv, struct wsm_buf *buf)
if (!event) if (!event)
return -ENOMEM; return -ENOMEM;
event->evt.id = __le32_to_cpu(WSM_GET32(buf)); event->evt.id = WSM_GET32(buf);
event->evt.data = __le32_to_cpu(WSM_GET32(buf)); event->evt.data = WSM_GET32(buf);
pr_debug("[WSM] Event: %d(%d)\n", pr_debug("[WSM] Event: %d(%d)\n",
event->evt.id, event->evt.data); event->evt.id, event->evt.data);
...@@ -1311,7 +1311,7 @@ int wsm_handle_rx(struct cw1200_common *priv, u16 id, ...@@ -1311,7 +1311,7 @@ int wsm_handle_rx(struct cw1200_common *priv, u16 id,
wsm_buf.begin = (u8 *)&wsm[0]; wsm_buf.begin = (u8 *)&wsm[0];
wsm_buf.data = (u8 *)&wsm[1]; wsm_buf.data = (u8 *)&wsm[1];
wsm_buf.end = &wsm_buf.begin[__le32_to_cpu(wsm->len)]; wsm_buf.end = &wsm_buf.begin[__le16_to_cpu(wsm->len)];
pr_debug("[WSM] <<< 0x%.4X (%td)\n", id, pr_debug("[WSM] <<< 0x%.4X (%td)\n", id,
wsm_buf.end - wsm_buf.begin); wsm_buf.end - wsm_buf.begin);
...@@ -1550,7 +1550,7 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv, ...@@ -1550,7 +1550,7 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv,
*/ */
pr_debug("[WSM] Convert probe request to scan.\n"); pr_debug("[WSM] Convert probe request to scan.\n");
wsm_lock_tx_async(priv); wsm_lock_tx_async(priv);
priv->pending_frame_id = __le32_to_cpu(wsm->packet_id); priv->pending_frame_id = wsm->packet_id;
if (queue_delayed_work(priv->workqueue, if (queue_delayed_work(priv->workqueue,
&priv->scan.probe_work, 0) <= 0) &priv->scan.probe_work, 0) <= 0)
wsm_unlock_tx(priv); wsm_unlock_tx(priv);
...@@ -1558,15 +1558,14 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv, ...@@ -1558,15 +1558,14 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv,
break; break;
case do_drop: case do_drop:
pr_debug("[WSM] Drop frame (0x%.4X).\n", fctl); pr_debug("[WSM] Drop frame (0x%.4X).\n", fctl);
BUG_ON(cw1200_queue_remove(queue, BUG_ON(cw1200_queue_remove(queue, wsm->packet_id));
__le32_to_cpu(wsm->packet_id)));
handled = true; handled = true;
break; break;
case do_wep: case do_wep:
pr_debug("[WSM] Issue set_default_wep_key.\n"); pr_debug("[WSM] Issue set_default_wep_key.\n");
wsm_lock_tx_async(priv); wsm_lock_tx_async(priv);
priv->wep_default_key_id = tx_info->control.hw_key->keyidx; priv->wep_default_key_id = tx_info->control.hw_key->keyidx;
priv->pending_frame_id = __le32_to_cpu(wsm->packet_id); priv->pending_frame_id = wsm->packet_id;
if (queue_work(priv->workqueue, &priv->wep_key_work) <= 0) if (queue_work(priv->workqueue, &priv->wep_key_work) <= 0)
wsm_unlock_tx(priv); wsm_unlock_tx(priv);
handled = true; handled = true;
......
...@@ -806,7 +806,7 @@ struct wsm_tx { ...@@ -806,7 +806,7 @@ struct wsm_tx {
struct wsm_hdr hdr; struct wsm_hdr hdr;
/* Packet identifier that meant to be used in completion. */ /* Packet identifier that meant to be used in completion. */
__le32 packet_id; u32 packet_id; /* Note this is actually a cookie */
/* WSM_TRANSMIT_RATE_... */ /* WSM_TRANSMIT_RATE_... */
u8 max_tx_rate; u8 max_tx_rate;
...@@ -825,18 +825,18 @@ struct wsm_tx { ...@@ -825,18 +825,18 @@ struct wsm_tx {
u8 flags; u8 flags;
/* Should be 0. */ /* Should be 0. */
__le32 reserved; u32 reserved;
/* The elapsed time in TUs, after the initial transmission */ /* The elapsed time in TUs, after the initial transmission */
/* of an MSDU, after which further attempts to transmit */ /* of an MSDU, after which further attempts to transmit */
/* the MSDU shall be terminated. Overrides the global */ /* the MSDU shall be terminated. Overrides the global */
/* dot11MaxTransmitMsduLifeTime setting [optional] */ /* dot11MaxTransmitMsduLifeTime setting [optional] */
/* Device will set the default value if this is 0. */ /* Device will set the default value if this is 0. */
__le32 expire_time; u32 expire_time;
/* WSM_HT_TX_... */ /* WSM_HT_TX_... */
__le32 ht_tx_parameters; __le32 ht_tx_parameters;
}; } __packed;
/* = sizeof(generic hi hdr) + sizeof(wsm hdr) + sizeof(alignment) */ /* = sizeof(generic hi hdr) + sizeof(wsm hdr) + sizeof(alignment) */
#define WSM_TX_EXTRA_HEADROOM (28) #define WSM_TX_EXTRA_HEADROOM (28)
...@@ -846,10 +846,10 @@ struct wsm_tx { ...@@ -846,10 +846,10 @@ struct wsm_tx {
struct wsm_rx { struct wsm_rx {
/* WSM_STATUS_... */ /* WSM_STATUS_... */
__le32 status; u32 status;
/* Specifies the channel of the received packet. */ /* Specifies the channel of the received packet. */
__le16 channel_number; u16 channel_number;
/* WSM_TRANSMIT_RATE_... */ /* WSM_TRANSMIT_RATE_... */
u8 rx_rate; u8 rx_rate;
...@@ -859,11 +859,8 @@ struct wsm_rx { ...@@ -859,11 +859,8 @@ struct wsm_rx {
u8 rcpi_rssi; u8 rcpi_rssi;
/* WSM_RX_STATUS_... */ /* WSM_RX_STATUS_... */
__le32 flags; u32 flags;
};
/* Payload */
u8 data[0];
} __packed;
/* = sizeof(generic hi hdr) + sizeof(wsm hdr) */ /* = sizeof(generic hi hdr) + sizeof(wsm hdr) */
#define WSM_RX_EXTRA_HEADROOM (16) #define WSM_RX_EXTRA_HEADROOM (16)
...@@ -1119,22 +1116,22 @@ int wsm_set_tx_queue_params(struct cw1200_common *priv, ...@@ -1119,22 +1116,22 @@ int wsm_set_tx_queue_params(struct cw1200_common *priv,
#define WSM_EDCA_PARAMS_RESP_ID 0x0413 #define WSM_EDCA_PARAMS_RESP_ID 0x0413
struct wsm_edca_queue_params { struct wsm_edca_queue_params {
/* CWmin (in slots) for the access class. */ /* CWmin (in slots) for the access class. */
__le16 cwmin; u16 cwmin;
/* CWmax (in slots) for the access class. */ /* CWmax (in slots) for the access class. */
__le16 cwmax; u16 cwmax;
/* AIFS (in slots) for the access class. */ /* AIFS (in slots) for the access class. */
__le16 aifns; u16 aifns;
/* TX OP Limit (in microseconds) for the access class. */ /* TX OP Limit (in microseconds) for the access class. */
__le16 txop_limit; u16 txop_limit;
/* dot11MaxReceiveLifetime to be used for the specified */ /* dot11MaxReceiveLifetime to be used for the specified */
/* the access class. Overrides the global */ /* the access class. Overrides the global */
/* dot11MaxReceiveLifetime value */ /* dot11MaxReceiveLifetime value */
__le32 max_rx_lifetime; u32 max_rx_lifetime;
} __packed; };
struct wsm_edca_params { struct wsm_edca_params {
/* NOTE: index is a linux queue id. */ /* NOTE: index is a linux queue id. */
...@@ -1147,12 +1144,12 @@ struct wsm_edca_params { ...@@ -1147,12 +1144,12 @@ struct wsm_edca_params {
__uapsd) \ __uapsd) \
do { \ do { \
struct wsm_edca_queue_params *p = &(__edca)->params[__queue]; \ struct wsm_edca_queue_params *p = &(__edca)->params[__queue]; \
p->cwmin = (__cw_min); \ p->cwmin = __cw_min; \
p->cwmax = (__cw_max); \ p->cwmax = __cw_max; \
p->aifns = (__aifs); \ p->aifns = __aifs; \
p->txop_limit = ((__txop) * TXOP_UNIT); \ p->txop_limit = ((__txop) * TXOP_UNIT); \
p->max_rx_lifetime = (__lifetime); \ p->max_rx_lifetime = __lifetime; \
(__edca)->uapsd_enable[__queue] = (__uapsd); \ (__edca)->uapsd_enable[__queue] = (__uapsd); \
} while (0) } while (0)
int wsm_set_edca_params(struct cw1200_common *priv, int wsm_set_edca_params(struct cw1200_common *priv,
...@@ -1475,7 +1472,7 @@ static inline int wsm_set_template_frame(struct cw1200_common *priv, ...@@ -1475,7 +1472,7 @@ static inline int wsm_set_template_frame(struct cw1200_common *priv,
u8 *p = skb_push(arg->skb, 4); u8 *p = skb_push(arg->skb, 4);
p[0] = arg->frame_type; p[0] = arg->frame_type;
p[1] = arg->rate; p[1] = arg->rate;
((u16 *)p)[1] = __cpu_to_le16(arg->skb->len - 4); ((__le16 *)p)[1] = __cpu_to_le16(arg->skb->len - 4);
ret = wsm_write_mib(priv, WSM_MIB_ID_TEMPLATE_FRAME, p, arg->skb->len); ret = wsm_write_mib(priv, WSM_MIB_ID_TEMPLATE_FRAME, p, arg->skb->len);
skb_pull(arg->skb, 4); skb_pull(arg->skb, 4);
return ret; return ret;
......
...@@ -3548,6 +3548,7 @@ static int ipw_load(struct ipw_priv *priv) ...@@ -3548,6 +3548,7 @@ static int ipw_load(struct ipw_priv *priv)
ipw_rx_queue_reset(priv, priv->rxq); ipw_rx_queue_reset(priv, priv->rxq);
if (!priv->rxq) { if (!priv->rxq) {
IPW_ERROR("Unable to initialize Rx queue\n"); IPW_ERROR("Unable to initialize Rx queue\n");
rc = -ENOMEM;
goto error; goto error;
} }
......
...@@ -1195,7 +1195,7 @@ static int libipw_parse_info_param(struct libipw_info_element ...@@ -1195,7 +1195,7 @@ static int libipw_parse_info_param(struct libipw_info_element
#ifdef CONFIG_LIBIPW_DEBUG #ifdef CONFIG_LIBIPW_DEBUG
p += snprintf(p, sizeof(rates_str) - p += snprintf(p, sizeof(rates_str) -
(p - rates_str), "%02X ", (p - rates_str), "%02X ",
network->rates[i]); network->rates_ex[i]);
#endif #endif
if (libipw_is_ofdm_rate if (libipw_is_ofdm_rate
(info_element->data[i])) { (info_element->data[i])) {
......
...@@ -128,16 +128,6 @@ config IWLWIFI_DEVICE_TRACING ...@@ -128,16 +128,6 @@ config IWLWIFI_DEVICE_TRACING
occur. occur.
endmenu endmenu
config IWLWIFI_DEVICE_TESTMODE
def_bool y
depends on IWLWIFI
depends on NL80211_TESTMODE
help
This option enables the testmode support for iwlwifi device through
NL80211_TESTMODE. This provide the capabilities of enable user space
validation applications to interacts with the device through the
generic netlink message via NL80211_TESTMODE channel.
config IWLWIFI_P2P config IWLWIFI_P2P
def_bool y def_bool y
bool "iwlwifi experimental P2P support" bool "iwlwifi experimental P2P support"
......
...@@ -13,7 +13,6 @@ iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o ...@@ -13,7 +13,6 @@ iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o
iwlwifi-objs += $(iwlwifi-m) iwlwifi-objs += $(iwlwifi-m)
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src) ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
......
...@@ -8,6 +8,5 @@ iwldvm-objs += scan.o led.o ...@@ -8,6 +8,5 @@ iwldvm-objs += scan.o led.o
iwldvm-objs += rxon.o devices.o iwldvm-objs += rxon.o devices.o
iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
...@@ -405,43 +405,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) ...@@ -405,43 +405,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
extern int iwl_alive_start(struct iwl_priv *priv); extern int iwl_alive_start(struct iwl_priv *priv);
/* testmode support */
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data,
int len);
extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct netlink_callback *cb,
void *data, int len);
extern void iwl_testmode_init(struct iwl_priv *priv);
extern void iwl_testmode_free(struct iwl_priv *priv);
#else
static inline
int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
return -ENOSYS;
}
static inline
int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
struct netlink_callback *cb,
void *data, int len)
{
return -ENOSYS;
}
static inline void iwl_testmode_init(struct iwl_priv *priv)
{
}
static inline void iwl_testmode_free(struct iwl_priv *priv)
{
}
#endif
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv, void iwl_print_rx_config_cmd(struct iwl_priv *priv,
enum iwl_rxon_context_id ctxid); enum iwl_rxon_context_id ctxid);
......
...@@ -52,8 +52,6 @@ ...@@ -52,8 +52,6 @@
#include "rs.h" #include "rs.h"
#include "tt.h" #include "tt.h"
#include "iwl-test.h"
/* CT-KILL constants */ /* CT-KILL constants */
#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */
#define CT_KILL_THRESHOLD 114 /* in Celsius */ #define CT_KILL_THRESHOLD 114 /* in Celsius */
...@@ -691,10 +689,6 @@ struct iwl_priv { ...@@ -691,10 +689,6 @@ struct iwl_priv {
struct iwl_spectrum_notification measure_report; struct iwl_spectrum_notification measure_report;
u8 measurement_status; u8 measurement_status;
#define IWL_OWNERSHIP_DRIVER 0
#define IWL_OWNERSHIP_TM 1
u8 ucode_owner;
/* ucode beacon time */ /* ucode beacon time */
u32 ucode_beacon_time; u32 ucode_beacon_time;
int missed_beacon_threshold; int missed_beacon_threshold;
...@@ -889,7 +883,7 @@ struct iwl_priv { ...@@ -889,7 +883,7 @@ struct iwl_priv {
#endif /* CONFIG_IWLWIFI_DEBUGFS */ #endif /* CONFIG_IWLWIFI_DEBUGFS */
struct iwl_nvm_data *nvm_data; struct iwl_nvm_data *nvm_data;
/* eeprom blob for debugfs/testmode */ /* eeprom blob for debugfs */
u8 *eeprom_blob; u8 *eeprom_blob;
size_t eeprom_blob_size; size_t eeprom_blob_size;
...@@ -905,11 +899,6 @@ struct iwl_priv { ...@@ -905,11 +899,6 @@ struct iwl_priv {
unsigned long blink_on, blink_off; unsigned long blink_on, blink_off;
bool led_registered; bool led_registered;
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
struct iwl_test tst;
u32 tm_fixed_rate;
#endif
/* WoWLAN GTK rekey data */ /* WoWLAN GTK rekey data */
u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
__le64 replay_ctr; __le64 replay_ctr;
......
...@@ -1288,12 +1288,6 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -1288,12 +1288,6 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (!(cmd->flags & CMD_ASYNC)) if (!(cmd->flags & CMD_ASYNC))
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->mutex);
if (priv->ucode_owner == IWL_OWNERSHIP_TM &&
!(cmd->flags & CMD_ON_DEMAND)) {
IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
return -EIO;
}
return iwl_trans_send_cmd(priv->trans, cmd); return iwl_trans_send_cmd(priv->trans, cmd);
} }
......
...@@ -1766,8 +1766,6 @@ struct ieee80211_ops iwlagn_hw_ops = { ...@@ -1766,8 +1766,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
.remain_on_channel = iwlagn_mac_remain_on_channel, .remain_on_channel = iwlagn_mac_remain_on_channel,
.cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel, .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel,
.rssi_callback = iwlagn_mac_rssi_callback, .rssi_callback = iwlagn_mac_rssi_callback,
CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump)
.set_tim = iwlagn_mac_set_tim, .set_tim = iwlagn_mac_set_tim,
}; };
......
...@@ -1105,8 +1105,6 @@ static int iwl_init_drv(struct iwl_priv *priv) ...@@ -1105,8 +1105,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
priv->agg_tids_count = 0; priv->agg_tids_count = 0;
priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
priv->rx_statistics_jiffies = jiffies; priv->rx_statistics_jiffies = jiffies;
/* Choose which receivers/antennas to use */ /* Choose which receivers/antennas to use */
...@@ -1172,12 +1170,6 @@ static void iwl_option_config(struct iwl_priv *priv) ...@@ -1172,12 +1170,6 @@ static void iwl_option_config(struct iwl_priv *priv)
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n"); IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
#endif #endif
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE enabled\n");
#else
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE disabled\n");
#endif
#ifdef CONFIG_IWLWIFI_P2P #ifdef CONFIG_IWLWIFI_P2P
IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n"); IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
#else #else
...@@ -1355,8 +1347,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1355,8 +1347,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
true : false; true : false;
/* enable/disable bt channel inhibition */ /* bt channel inhibition enabled*/
priv->bt_ch_announce = iwlwifi_mod_params.bt_ch_announce; priv->bt_ch_announce = true;
IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
(priv->bt_ch_announce) ? "On" : "Off"); (priv->bt_ch_announce) ? "On" : "Off");
...@@ -1451,7 +1443,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1451,7 +1443,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
********************/ ********************/
iwl_setup_deferred_work(priv); iwl_setup_deferred_work(priv);
iwl_setup_rx_handlers(priv); iwl_setup_rx_handlers(priv);
iwl_testmode_init(priv);
iwl_power_initialize(priv); iwl_power_initialize(priv);
iwl_tt_initialize(priv); iwl_tt_initialize(priv);
...@@ -1488,7 +1479,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1488,7 +1479,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
iwlagn_mac_unregister(priv); iwlagn_mac_unregister(priv);
out_destroy_workqueue: out_destroy_workqueue:
iwl_tt_exit(priv); iwl_tt_exit(priv);
iwl_testmode_free(priv);
iwl_cancel_deferred_work(priv); iwl_cancel_deferred_work(priv);
destroy_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue);
priv->workqueue = NULL; priv->workqueue = NULL;
...@@ -1510,7 +1500,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) ...@@ -1510,7 +1500,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
iwl_testmode_free(priv);
iwlagn_mac_unregister(priv); iwlagn_mac_unregister(priv);
iwl_tt_exit(priv); iwl_tt_exit(priv);
......
...@@ -351,12 +351,6 @@ static void rs_program_fix_rate(struct iwl_priv *priv, ...@@ -351,12 +351,6 @@ 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_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
lq_sta->active_mimo3_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_TESTMODE
/* 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", IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
...@@ -419,23 +413,18 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, ...@@ -419,23 +413,18 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
load = rs_tl_get_load(lq_data, tid); load = rs_tl_get_load(lq_data, tid);
if ((iwlwifi_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid);
sta->addr, tid); ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
ret = ieee80211_start_tx_ba_session(sta, tid, 5000); if (ret == -EAGAIN) {
if (ret == -EAGAIN) { /*
/* * driver and mac80211 is out of sync
* driver and mac80211 is out of sync * this might be cause by reloading firmware
* this might be cause by reloading firmware * stop the tx ba session here
* stop the tx ba session here */
*/ IWL_ERR(priv, "Fail start Tx agg on tid: %d\n",
IWL_ERR(priv, "Fail start Tx agg on tid: %d\n", tid);
tid); ieee80211_stop_tx_ba_session(sta, tid);
ieee80211_stop_tx_ba_session(sta, tid);
}
} else {
IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d "
"because load = %u\n", tid, load);
} }
return ret; return ret;
} }
...@@ -1083,11 +1072,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, ...@@ -1083,11 +1072,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
if (sta && sta->supp_rates[sband->band]) if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, skb, sta, lq_sta); rs_rate_scale_perform(priv, skb, sta, lq_sta);
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_TESTMODE)
if ((priv->tm_fixed_rate) &&
(priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
rs_program_fix_rate(priv, lq_sta);
#endif
if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist) if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist)
rs_bt_update_lq(priv, ctx, lq_sta); rs_bt_update_lq(priv, ctx, lq_sta);
} }
...@@ -2913,9 +2897,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i ...@@ -2913,9 +2897,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
if (sband->band == IEEE80211_BAND_5GHZ) if (sband->band == IEEE80211_BAND_5GHZ)
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_agg = 0; lq_sta->is_agg = 0;
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
priv->tm_fixed_rate = 0;
#endif
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->dbg_fixed_rate = 0; lq_sta->dbg_fixed_rate = 0;
#endif #endif
......
...@@ -335,8 +335,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv, ...@@ -335,8 +335,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
if (msecs < 99) if (msecs < 99)
return; return;
if (iwlwifi_mod_params.plcp_check && if (!iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
!iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
iwl_force_rf_reset(priv, false); iwl_force_rf_reset(priv, false);
} }
...@@ -1120,32 +1119,17 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, ...@@ -1120,32 +1119,17 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
*/ */
iwl_notification_wait_notify(&priv->notif_wait, pkt); iwl_notification_wait_notify(&priv->notif_wait, pkt);
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE /* Based on type of command response or notification,
/* * handle those that need handling via function in
* RX data may be forwarded to userspace in one * rx_handlers table. See iwl_setup_rx_handlers() */
* of two cases: the user owns the fw through testmode or when if (priv->rx_handlers[pkt->hdr.cmd]) {
* the user requested to monitor the rx w/o affecting the regular flow. priv->rx_handlers_stats[pkt->hdr.cmd]++;
* In these cases the iwl_test object will handle forwarding the rx err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
* data to user space. } else {
* Note that if the ownership flag != IWL_OWNERSHIP_TM the flow /* No handling needed */
* continues. IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n",
*/ iwl_dvm_get_cmd_string(pkt->hdr.cmd),
iwl_test_rx(&priv->tst, rxb); pkt->hdr.cmd);
#endif
if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
/* 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->rx_handlers_stats[pkt->hdr.cmd]++;
err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
} else {
/* No handling needed */
IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n",
iwl_dvm_get_cmd_string(pkt->hdr.cmd),
pkt->hdr.cmd);
}
} }
return err; return err;
} }
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2010 - 2013 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 COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <net/net_namespace.h>
#include <linux/netdevice.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <net/netlink.h>
#include "iwl-debug.h"
#include "iwl-trans.h"
#include "dev.h"
#include "agn.h"
#include "iwl-test.h"
#include "iwl-testmode.h"
static int iwl_testmode_send_cmd(struct iwl_op_mode *op_mode,
struct iwl_host_cmd *cmd)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
return iwl_dvm_send_cmd(priv, cmd);
}
static bool iwl_testmode_valid_hw_addr(u32 addr)
{
if (iwlagn_hw_valid_rtc_data_addr(addr))
return true;
if (IWLAGN_RTC_INST_LOWER_BOUND <= addr &&
addr < IWLAGN_RTC_INST_UPPER_BOUND)
return true;
return false;
}
static u32 iwl_testmode_get_fw_ver(struct iwl_op_mode *op_mode)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
return priv->fw->ucode_ver;
}
static struct sk_buff*
iwl_testmode_alloc_reply(struct iwl_op_mode *op_mode, int len)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
return cfg80211_testmode_alloc_reply_skb(priv->hw->wiphy, len);
}
static int iwl_testmode_reply(struct iwl_op_mode *op_mode, struct sk_buff *skb)
{
return cfg80211_testmode_reply(skb);
}
static struct sk_buff *iwl_testmode_alloc_event(struct iwl_op_mode *op_mode,
int len)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
return cfg80211_testmode_alloc_event_skb(priv->hw->wiphy, len,
GFP_ATOMIC);
}
static void iwl_testmode_event(struct iwl_op_mode *op_mode, struct sk_buff *skb)
{
return cfg80211_testmode_event(skb, GFP_ATOMIC);
}
static struct iwl_test_ops tst_ops = {
.send_cmd = iwl_testmode_send_cmd,
.valid_hw_addr = iwl_testmode_valid_hw_addr,
.get_fw_ver = iwl_testmode_get_fw_ver,
.alloc_reply = iwl_testmode_alloc_reply,
.reply = iwl_testmode_reply,
.alloc_event = iwl_testmode_alloc_event,
.event = iwl_testmode_event,
};
void iwl_testmode_init(struct iwl_priv *priv)
{
iwl_test_init(&priv->tst, priv->trans, &tst_ops);
}
void iwl_testmode_free(struct iwl_priv *priv)
{
iwl_test_free(&priv->tst);
}
static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
{
struct iwl_notification_wait calib_wait;
static const u8 calib_complete[] = {
CALIBRATION_COMPLETE_NOTIFICATION
};
int ret;
iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
calib_complete, ARRAY_SIZE(calib_complete),
NULL, NULL);
ret = iwl_init_alive_start(priv);
if (ret) {
IWL_ERR(priv, "Fail init calibration: %d\n", ret);
goto cfg_init_calib_error;
}
ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
if (ret)
IWL_ERR(priv, "Error detecting"
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
return ret;
cfg_init_calib_error:
iwl_remove_notification(&priv->notif_wait, &calib_wait);
return ret;
}
/*
* This function handles the user application commands for driver.
*
* It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
* handlers respectively.
*
* If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
* value of the actual command execution is replied to the user application.
*
* If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
* is used for carry the message while IWL_TM_ATTR_COMMAND must set to
* IWL_TM_CMD_DEV2APP_SYNC_RSP.
*
* @hw: ieee80211_hw object that represents the device
* @tb: gnl message fields from the user space
*/
static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_trans *trans = priv->trans;
struct sk_buff *skb;
unsigned char *rsp_data_ptr = NULL;
int status = 0, rsp_data_len = 0;
u32 inst_size = 0, data_size = 0;
const struct fw_img *img;
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
rsp_data_ptr = (unsigned char *)priv->cfg->name;
rsp_data_len = strlen(priv->cfg->name);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
rsp_data_len + 20);
if (!skb) {
IWL_ERR(priv, "Memory allocation fail\n");
return -ENOMEM;
}
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
IWL_TM_CMD_DEV2APP_SYNC_RSP) ||
nla_put(skb, IWL_TM_ATTR_SYNC_RSP,
rsp_data_len, rsp_data_ptr))
goto nla_put_failure;
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_ERR(priv, "Error sending msg : %d\n", status);
break;
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
if (status)
IWL_ERR(priv, "Error loading init ucode: %d\n", status);
break;
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
iwl_testmode_cfg_init_calib(priv);
priv->ucode_loaded = false;
iwl_trans_stop_device(trans);
break;
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
if (status) {
IWL_ERR(priv,
"Error loading runtime ucode: %d\n", status);
break;
}
status = iwl_alive_start(priv);
if (status)
IWL_ERR(priv,
"Error starting the device: %d\n", status);
break;
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
iwl_scan_cancel_timeout(priv, 200);
priv->ucode_loaded = false;
iwl_trans_stop_device(trans);
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
if (status) {
IWL_ERR(priv,
"Error loading WOWLAN ucode: %d\n", status);
break;
}
status = iwl_alive_start(priv);
if (status)
IWL_ERR(priv,
"Error starting the device: %d\n", status);
break;
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
if (priv->eeprom_blob) {
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
priv->eeprom_blob_size + 20);
if (!skb) {
IWL_ERR(priv, "Memory allocation fail\n");
return -ENOMEM;
}
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
IWL_TM_CMD_DEV2APP_EEPROM_RSP) ||
nla_put(skb, IWL_TM_ATTR_EEPROM,
priv->eeprom_blob_size,
priv->eeprom_blob))
goto nla_put_failure;
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_ERR(priv, "Error sending msg : %d\n",
status);
} else
return -ENODATA;
break;
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
if (!tb[IWL_TM_ATTR_FIXRATE]) {
IWL_ERR(priv, "Missing fixrate setting\n");
return -ENOMSG;
}
priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
break;
case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8);
if (!skb) {
IWL_ERR(priv, "Memory allocation fail\n");
return -ENOMEM;
}
if (!priv->ucode_loaded) {
IWL_ERR(priv, "No uCode has not been loaded\n");
return -EINVAL;
} else {
img = &priv->fw->img[priv->cur_ucode];
inst_size = img->sec[IWL_UCODE_SECTION_INST].len;
data_size = img->sec[IWL_UCODE_SECTION_DATA].len;
}
if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) ||
nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) ||
nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size))
goto nla_put_failure;
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_ERR(priv, "Error sending msg : %d\n", status);
break;
default:
IWL_ERR(priv, "Unknown testmode driver command ID\n");
return -ENOSYS;
}
return status;
nla_put_failure:
kfree_skb(skb);
return -EMSGSIZE;
}
/*
* This function handles the user application switch ucode ownership.
*
* It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
* decide who the current owner of the uCode
*
* If the current owner is OWNERSHIP_TM, then the only host command
* can deliver to uCode is from testmode, all the other host commands
* will dropped.
*
* default driver is the owner of uCode in normal operational mode
*
* @hw: ieee80211_hw object that represents the device
* @tb: gnl message fields from the user space
*/
static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
u8 owner;
if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
IWL_ERR(priv, "Missing ucode owner\n");
return -ENOMSG;
}
owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
if (owner == IWL_OWNERSHIP_DRIVER) {
priv->ucode_owner = owner;
iwl_test_enable_notifications(&priv->tst, false);
} else if (owner == IWL_OWNERSHIP_TM) {
priv->ucode_owner = owner;
iwl_test_enable_notifications(&priv->tst, true);
} else {
IWL_ERR(priv, "Invalid owner\n");
return -EINVAL;
}
return 0;
}
/* The testmode gnl message handler that takes the gnl message from the
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
* invoke the corresponding handlers.
*
* This function is invoked when there is user space application sending
* gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
* by nl80211.
*
* It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
* dispatching it to the corresponding handler.
*
* If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
* -ENOSYS is replied to the user application if the command is unknown;
* Otherwise, the command is dispatched to the respective handler.
*
* @hw: ieee80211_hw object that represents the device
* @data: pointer to user space message
* @len: length in byte of @data
*/
int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
struct nlattr *tb[IWL_TM_ATTR_MAX];
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int result;
result = iwl_test_parse(&priv->tst, tb, data, len);
if (result)
return result;
/* in case multiple accesses to the device happens */
mutex_lock(&priv->mutex);
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_UCODE:
case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
case IWL_TM_CMD_APP2DEV_END_TRACE:
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
result = iwl_test_handle_cmd(&priv->tst, tb);
break;
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
result = iwl_testmode_driver(hw, tb);
break;
case IWL_TM_CMD_APP2DEV_OWNERSHIP:
IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
result = iwl_testmode_ownership(hw, tb);
break;
default:
IWL_ERR(priv, "Unknown testmode command\n");
result = -ENOSYS;
break;
}
mutex_unlock(&priv->mutex);
if (result)
IWL_ERR(priv, "Test cmd failed result=%d\n", result);
return result;
}
int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
struct netlink_callback *cb,
void *data, int len)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int result;
u32 cmd;
if (cb->args[3]) {
/* offset by 1 since commands start at 0 */
cmd = cb->args[3] - 1;
} else {
struct nlattr *tb[IWL_TM_ATTR_MAX];
result = iwl_test_parse(&priv->tst, tb, data, len);
if (result)
return result;
cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
cb->args[3] = cmd + 1;
}
/* in case multiple accesses to the device happens */
mutex_lock(&priv->mutex);
result = iwl_test_dump(&priv->tst, cmd, skb, cb);
mutex_unlock(&priv->mutex);
return result;
}
...@@ -162,18 +162,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, ...@@ -162,18 +162,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
if (ieee80211_is_data(fc)) { if (ieee80211_is_data(fc)) {
tx_cmd->initial_rate_index = 0; tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
if (priv->tm_fixed_rate) {
/*
* rate overwrite by testmode
* we not only send lq command to change rate
* we also re-enforce per data pkt base.
*/
tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK;
memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate,
sizeof(tx_cmd->rate_n_flags));
}
#endif
return; return;
} else if (ieee80211_is_back_req(fc)) } else if (ieee80211_is_back_req(fc))
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册