mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 12:37:49 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
b5ddedc9cc
@ -214,6 +214,21 @@ config HERMES
|
||||
configure your card and that /etc/pcmcia/wireless.opts works :
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
|
||||
|
||||
config HERMES_CACHE_FW_ON_INIT
|
||||
bool "Cache Hermes firmware on driver initialisation"
|
||||
depends on HERMES
|
||||
default y
|
||||
---help---
|
||||
Say Y to cache any firmware required by the Hermes drivers
|
||||
on startup. The firmware will remain cached until the
|
||||
driver is unloaded. The cache uses 64K of RAM.
|
||||
|
||||
Otherwise load the firmware from userspace as required. In
|
||||
this case the driver should be unloaded and restarted
|
||||
whenever the firmware is changed.
|
||||
|
||||
If you are not sure, say Y.
|
||||
|
||||
config APPLE_AIRPORT
|
||||
tristate "Apple Airport support (built-in)"
|
||||
depends on PPC_PMAC && HERMES
|
||||
@ -508,7 +523,7 @@ config RTL8180
|
||||
|
||||
config RTL8187
|
||||
tristate "Realtek 8187 and 8187B USB support"
|
||||
depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
|
||||
depends on MAC80211 && USB && WLAN_80211
|
||||
select EEPROM_93CX6
|
||||
---help---
|
||||
This is a driver for RTL8187 and RTL8187B based cards.
|
||||
|
@ -821,13 +821,6 @@ struct ath5k_athchan_2ghz {
|
||||
return (false); \
|
||||
} while (0)
|
||||
|
||||
enum ath5k_ant_setting {
|
||||
AR5K_ANT_VARIABLE = 0, /* variable by programming */
|
||||
AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
|
||||
AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
|
||||
AR5K_ANT_MAX = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* Hardware interrupt abstraction
|
||||
*/
|
||||
|
@ -106,7 +106,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
||||
{
|
||||
struct ath5k_hw *ah;
|
||||
struct pci_dev *pdev = sc->pdev;
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 mac[ETH_ALEN] = {};
|
||||
int ret;
|
||||
u32 srev;
|
||||
|
||||
@ -317,15 +317,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* Set MAC address */
|
||||
ret = ath5k_eeprom_read_mac(ah, mac);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
|
||||
sc->pdev->device);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* MAC address is cleared until add_interface */
|
||||
ath5k_hw_set_lladdr(ah, mac);
|
||||
|
||||
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
|
||||
memset(ah->ah_bssid, 0xff, ETH_ALEN);
|
||||
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
|
||||
|
@ -200,7 +200,7 @@ static int ath5k_pci_resume(struct pci_dev *pdev);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct pci_driver ath5k_pci_driver = {
|
||||
.name = "ath5k_pci",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = ath5k_pci_id_table,
|
||||
.probe = ath5k_pci_probe,
|
||||
.remove = __devexit_p(ath5k_pci_remove),
|
||||
@ -707,7 +707,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 mac[ETH_ALEN] = {};
|
||||
int ret;
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
|
||||
@ -777,7 +777,13 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
|
||||
setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
|
||||
|
||||
ath5k_hw_get_lladdr(ah, mac);
|
||||
ret = ath5k_eeprom_read_mac(ah, mac);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
|
||||
sc->pdev->device);
|
||||
goto err_queues;
|
||||
}
|
||||
|
||||
SET_IEEE80211_PERM_ADDR(hw, mac);
|
||||
/* All MAC address bits matter for ACKs */
|
||||
memset(sc->bssidmask, 0xff, ETH_ALEN);
|
||||
@ -2765,6 +2771,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
/* Set to a reasonable value. Note that this will
|
||||
* be set to mac80211's value at ath5k_config(). */
|
||||
sc->bintval = 1000;
|
||||
ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
|
||||
|
||||
ret = 0;
|
||||
end:
|
||||
@ -2777,11 +2784,13 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
u8 mac[ETH_ALEN] = {};
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
if (sc->vif != conf->vif)
|
||||
goto end;
|
||||
|
||||
ath5k_hw_set_lladdr(sc->ah, mac);
|
||||
sc->vif = NULL;
|
||||
end:
|
||||
mutex_unlock(&sc->lock);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,128 @@
|
||||
#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
|
||||
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
|
||||
|
||||
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
|
||||
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
|
||||
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
|
||||
#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
|
||||
#define AR5K_EEPROM_INFO_CKSUM 0xffff
|
||||
#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
|
||||
|
||||
#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
|
||||
#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
|
||||
#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
|
||||
#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
|
||||
#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
|
||||
#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
|
||||
#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
|
||||
#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
|
||||
#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
|
||||
#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */
|
||||
#define AR5K_EEPROM_VERSION_4_4 0x4004
|
||||
#define AR5K_EEPROM_VERSION_4_5 0x4005
|
||||
#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
|
||||
#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */
|
||||
#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */
|
||||
#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */
|
||||
#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */
|
||||
#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */
|
||||
|
||||
#define AR5K_EEPROM_MODE_11A 0
|
||||
#define AR5K_EEPROM_MODE_11B 1
|
||||
#define AR5K_EEPROM_MODE_11G 2
|
||||
|
||||
#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
|
||||
#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
|
||||
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
|
||||
#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
|
||||
|
||||
#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
|
||||
#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
|
||||
#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
|
||||
#define AR5K_EEPROM_RFKILL_POLARITY_S 1
|
||||
|
||||
/* Newer EEPROMs are using a different offset */
|
||||
#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
|
||||
(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
|
||||
|
||||
#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
|
||||
#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff))
|
||||
#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff))
|
||||
|
||||
/* Misc values available since EEPROM 4.0 */
|
||||
#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4)
|
||||
#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
|
||||
#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1)
|
||||
#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
|
||||
|
||||
#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
|
||||
#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
|
||||
#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
|
||||
#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1)
|
||||
|
||||
#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6)
|
||||
#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff)
|
||||
#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff)
|
||||
|
||||
#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7)
|
||||
#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f)
|
||||
#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff)
|
||||
|
||||
#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8)
|
||||
#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff)
|
||||
#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3)
|
||||
#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3)
|
||||
|
||||
#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9)
|
||||
#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1)
|
||||
#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1)
|
||||
#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1)
|
||||
#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1)
|
||||
#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf)
|
||||
#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1)
|
||||
#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf)
|
||||
|
||||
#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
|
||||
#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8)
|
||||
#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8)
|
||||
#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1)
|
||||
|
||||
/* calibration settings */
|
||||
#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
|
||||
#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
|
||||
#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
|
||||
#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
|
||||
#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */
|
||||
#define AR5K_EEPROM_GROUP1_OFFSET 0x0
|
||||
#define AR5K_EEPROM_GROUP2_OFFSET 0x5
|
||||
#define AR5K_EEPROM_GROUP3_OFFSET 0x37
|
||||
#define AR5K_EEPROM_GROUP4_OFFSET 0x46
|
||||
#define AR5K_EEPROM_GROUP5_OFFSET 0x55
|
||||
#define AR5K_EEPROM_GROUP6_OFFSET 0x65
|
||||
#define AR5K_EEPROM_GROUP7_OFFSET 0x69
|
||||
#define AR5K_EEPROM_GROUP8_OFFSET 0x6f
|
||||
|
||||
#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
|
||||
AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
|
||||
#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
|
||||
AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
|
||||
#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
|
||||
AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
|
||||
|
||||
/* [3.1 - 3.3] */
|
||||
#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
|
||||
#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
|
||||
|
||||
#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
|
||||
#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
|
||||
#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
|
||||
@ -42,72 +164,6 @@
|
||||
#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
|
||||
#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
|
||||
#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
|
||||
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
|
||||
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
|
||||
#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
|
||||
#define AR5K_EEPROM_INFO_CKSUM 0xffff
|
||||
#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
|
||||
|
||||
#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
|
||||
#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
|
||||
#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
|
||||
#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
|
||||
#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
|
||||
#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
|
||||
#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
|
||||
#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
|
||||
#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
|
||||
#define AR5K_EEPROM_VERSION_4_3 0x4003
|
||||
#define AR5K_EEPROM_VERSION_4_4 0x4004
|
||||
#define AR5K_EEPROM_VERSION_4_5 0x4005
|
||||
#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
|
||||
#define AR5K_EEPROM_VERSION_4_7 0x4007
|
||||
|
||||
#define AR5K_EEPROM_MODE_11A 0
|
||||
#define AR5K_EEPROM_MODE_11B 1
|
||||
#define AR5K_EEPROM_MODE_11G 2
|
||||
|
||||
#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
|
||||
#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
|
||||
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
|
||||
#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
|
||||
|
||||
#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
|
||||
#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
|
||||
#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
|
||||
#define AR5K_EEPROM_RFKILL_POLARITY_S 1
|
||||
|
||||
/* Newer EEPROMs are using a different offset */
|
||||
#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
|
||||
(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
|
||||
|
||||
#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
|
||||
#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
|
||||
#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
|
||||
|
||||
/* calibration settings */
|
||||
#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
|
||||
#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
|
||||
#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
|
||||
#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
|
||||
|
||||
/* [3.1 - 3.3] */
|
||||
#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
|
||||
#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
|
||||
|
||||
/* Misc values available since EEPROM 4.0 */
|
||||
#define AR5K_EEPROM_MISC0 0x00c4
|
||||
#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
|
||||
#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
|
||||
#define AR5K_EEPROM_MISC1 0x00c5
|
||||
#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
|
||||
#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
|
||||
|
||||
|
||||
/* Some EEPROM defines */
|
||||
#define AR5K_EEPROM_EEP_SCALE 100
|
||||
@ -115,8 +171,11 @@
|
||||
#define AR5K_EEPROM_N_MODES 3
|
||||
#define AR5K_EEPROM_N_5GHZ_CHAN 10
|
||||
#define AR5K_EEPROM_N_2GHZ_CHAN 3
|
||||
#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
|
||||
#define AR5K_EEPROM_MAX_CHAN 10
|
||||
#define AR5K_EEPROM_N_PWR_POINTS_5111 11
|
||||
#define AR5K_EEPROM_N_PCDAC 11
|
||||
#define AR5K_EEPROM_N_PHASE_CAL 5
|
||||
#define AR5K_EEPROM_N_TEST_FREQ 8
|
||||
#define AR5K_EEPROM_N_EDGES 8
|
||||
#define AR5K_EEPROM_N_INTERCEPTS 11
|
||||
@ -136,6 +195,8 @@
|
||||
#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
|
||||
#define AR5K_EEPROM_N_XPD0_POINTS 4
|
||||
#define AR5K_EEPROM_N_XPD3_POINTS 3
|
||||
#define AR5K_EEPROM_N_PD_GAINS 4
|
||||
#define AR5K_EEPROM_N_PD_POINTS 5
|
||||
#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
|
||||
#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
|
||||
#define AR5K_EEPROM_POWER_M 0x3f
|
||||
@ -158,8 +219,99 @@
|
||||
#define AR5K_EEPROM_READ_HDR(_o, _v) \
|
||||
AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
|
||||
|
||||
/* Struct to hold EEPROM calibration data */
|
||||
enum ath5k_ant_setting {
|
||||
AR5K_ANT_VARIABLE = 0, /* variable by programming */
|
||||
AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
|
||||
AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
|
||||
AR5K_ANT_MAX = 3,
|
||||
};
|
||||
|
||||
enum ath5k_ctl_mode {
|
||||
AR5K_CTL_11A = 0,
|
||||
AR5K_CTL_11B = 1,
|
||||
AR5K_CTL_11G = 2,
|
||||
AR5K_CTL_TURBO = 3,
|
||||
AR5K_CTL_108G = 4,
|
||||
AR5K_CTL_2GHT20 = 5,
|
||||
AR5K_CTL_5GHT20 = 6,
|
||||
AR5K_CTL_2GHT40 = 7,
|
||||
AR5K_CTL_5GHT40 = 8,
|
||||
AR5K_CTL_MODE_M = 15,
|
||||
};
|
||||
|
||||
/* Per channel calibration data, used for power table setup */
|
||||
struct ath5k_chan_pcal_info_rf5111 {
|
||||
/* Power levels in half dbm units
|
||||
* for one power curve. */
|
||||
u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
|
||||
/* PCDAC table steps
|
||||
* for the above values */
|
||||
u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
|
||||
/* Starting PCDAC step */
|
||||
u8 pcdac_min;
|
||||
/* Final PCDAC step */
|
||||
u8 pcdac_max;
|
||||
};
|
||||
|
||||
struct ath5k_chan_pcal_info_rf5112 {
|
||||
/* Power levels in quarter dBm units
|
||||
* for lower (0) and higher (3)
|
||||
* level curves */
|
||||
s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
|
||||
s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
|
||||
/* PCDAC table steps
|
||||
* for the above values */
|
||||
u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
|
||||
u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
|
||||
};
|
||||
|
||||
struct ath5k_chan_pcal_info_rf2413 {
|
||||
/* Starting pwr/pddac values */
|
||||
s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
|
||||
u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
|
||||
/* (pwr,pddac) points */
|
||||
s8 pwr[AR5K_EEPROM_N_PD_GAINS]
|
||||
[AR5K_EEPROM_N_PD_POINTS];
|
||||
u8 pddac[AR5K_EEPROM_N_PD_GAINS]
|
||||
[AR5K_EEPROM_N_PD_POINTS];
|
||||
};
|
||||
|
||||
struct ath5k_chan_pcal_info {
|
||||
/* Frequency */
|
||||
u16 freq;
|
||||
/* Max available power */
|
||||
s8 max_pwr;
|
||||
union {
|
||||
struct ath5k_chan_pcal_info_rf5111 rf5111_info;
|
||||
struct ath5k_chan_pcal_info_rf5112 rf5112_info;
|
||||
struct ath5k_chan_pcal_info_rf2413 rf2413_info;
|
||||
};
|
||||
};
|
||||
|
||||
/* Per rate calibration data for each mode, used for power table setup */
|
||||
struct ath5k_rate_pcal_info {
|
||||
u16 freq; /* Frequency */
|
||||
/* Power level for 6-24Mbit/s rates */
|
||||
u16 target_power_6to24;
|
||||
/* Power level for 36Mbit rate */
|
||||
u16 target_power_36;
|
||||
/* Power level for 48Mbit rate */
|
||||
u16 target_power_48;
|
||||
/* Power level for 54Mbit rate */
|
||||
u16 target_power_54;
|
||||
};
|
||||
|
||||
/* Power edges for conformance test limits */
|
||||
struct ath5k_edge_power {
|
||||
u16 freq;
|
||||
u16 edge; /* in half dBm */
|
||||
bool flag;
|
||||
};
|
||||
|
||||
/* EEPROM calibration data */
|
||||
struct ath5k_eeprom_info {
|
||||
|
||||
/* Header information */
|
||||
u16 ee_magic;
|
||||
u16 ee_protect;
|
||||
u16 ee_regdomain;
|
||||
@ -168,6 +320,11 @@ struct ath5k_eeprom_info {
|
||||
u16 ee_ant_gain;
|
||||
u16 ee_misc0;
|
||||
u16 ee_misc1;
|
||||
u16 ee_misc2;
|
||||
u16 ee_misc3;
|
||||
u16 ee_misc4;
|
||||
u16 ee_misc5;
|
||||
u16 ee_misc6;
|
||||
u16 ee_cck_ofdm_gain_delta;
|
||||
u16 ee_cck_ofdm_power_delta;
|
||||
u16 ee_scaled_cck_delta;
|
||||
@ -185,7 +342,7 @@ struct ath5k_eeprom_info {
|
||||
u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_xr_power[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
|
||||
u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
|
||||
u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
|
||||
@ -198,18 +355,40 @@ struct ath5k_eeprom_info {
|
||||
u16 ee_x_gain[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_i_gain[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
|
||||
|
||||
/* Unused */
|
||||
/* Power calibration data */
|
||||
u16 ee_false_detect[AR5K_EEPROM_N_MODES];
|
||||
u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
|
||||
u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/
|
||||
|
||||
/* Number of pd gain curves per mode (RF2413) */
|
||||
u8 ee_pd_gains[AR5K_EEPROM_N_MODES];
|
||||
|
||||
u8 ee_n_piers[AR5K_EEPROM_N_MODES];
|
||||
struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
|
||||
struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN];
|
||||
struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN];
|
||||
|
||||
/* Per rate target power levels */
|
||||
u16 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
|
||||
struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
|
||||
struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN];
|
||||
struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN];
|
||||
|
||||
/* Conformance test limits (Unused) */
|
||||
u16 ee_ctls;
|
||||
u16 ee_ctl[AR5K_EEPROM_MAX_CTLS];
|
||||
struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
|
||||
|
||||
/* Noise Floor Calibration settings */
|
||||
s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
|
||||
s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
|
||||
s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
|
||||
s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
|
||||
s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
|
||||
s8 ee_pd_gain_overlap;
|
||||
|
||||
u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
|
||||
};
|
||||
|
||||
|
@ -674,7 +674,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
||||
(ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
|
||||
0xffffc07f);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
|
||||
(ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
|
||||
(ee->ee_atn_tx_rx[ee_mode] << 12) & 0x3f000,
|
||||
0xfffc0fff);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
|
||||
(ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
|
||||
|
@ -9,7 +9,6 @@ ath9k-y += hw.o \
|
||||
main.o \
|
||||
recv.o \
|
||||
xmit.o \
|
||||
rc.o \
|
||||
core.o
|
||||
rc.o
|
||||
|
||||
obj-$(CONFIG_ATH9K) += ath9k.o
|
||||
|
@ -401,22 +401,6 @@ enum ath9k_int {
|
||||
ATH9K_INT_NOCARD = 0xffffffff
|
||||
};
|
||||
|
||||
struct ath9k_rate_table {
|
||||
int rateCount;
|
||||
u8 rateCodeToIndex[256];
|
||||
struct {
|
||||
u8 valid;
|
||||
u8 phy;
|
||||
u32 rateKbps;
|
||||
u8 rateCode;
|
||||
u8 shortPreamble;
|
||||
u8 dot11Rate;
|
||||
u8 controlRate;
|
||||
u16 lpAckDuration;
|
||||
u16 spAckDuration;
|
||||
} info[32];
|
||||
};
|
||||
|
||||
#define ATH9K_RATESERIES_RTS_CTS 0x0001
|
||||
#define ATH9K_RATESERIES_2040 0x0002
|
||||
#define ATH9K_RATESERIES_HALFGI 0x0004
|
||||
@ -492,12 +476,10 @@ struct ath9k_channel {
|
||||
(((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
|
||||
(((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
|
||||
(((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
|
||||
#define IS_CHAN_B(_c) (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B)
|
||||
#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
|
||||
(((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
|
||||
(((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
|
||||
(((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
|
||||
#define IS_CHAN_CCK(_c) (((_c)->channelFlags & CHANNEL_CCK) != 0)
|
||||
#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
|
||||
#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
|
||||
#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
|
||||
@ -506,6 +488,7 @@ struct ath9k_channel {
|
||||
#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
|
||||
|
||||
/* These macros check chanmode and not channelFlags */
|
||||
#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
|
||||
#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \
|
||||
((_c)->chanmode == CHANNEL_G_HT20))
|
||||
#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \
|
||||
@ -702,13 +685,19 @@ enum ath9k_ani_cmd {
|
||||
ATH9K_ANI_ALL = 0xff
|
||||
};
|
||||
|
||||
enum phytype {
|
||||
PHY_DS,
|
||||
PHY_FH,
|
||||
PHY_OFDM,
|
||||
PHY_HT,
|
||||
enum {
|
||||
WLAN_RC_PHY_OFDM,
|
||||
WLAN_RC_PHY_CCK,
|
||||
WLAN_RC_PHY_HT_20_SS,
|
||||
WLAN_RC_PHY_HT_20_DS,
|
||||
WLAN_RC_PHY_HT_40_SS,
|
||||
WLAN_RC_PHY_HT_40_DS,
|
||||
WLAN_RC_PHY_HT_20_SS_HGI,
|
||||
WLAN_RC_PHY_HT_20_DS_HGI,
|
||||
WLAN_RC_PHY_HT_40_SS_HGI,
|
||||
WLAN_RC_PHY_HT_40_DS_HGI,
|
||||
WLAN_RC_PHY_MAX
|
||||
};
|
||||
#define PHY_CCK PHY_DS
|
||||
|
||||
enum ath9k_tp_scale {
|
||||
ATH9K_TP_SCALE_MAX = 0,
|
||||
@ -828,6 +817,8 @@ struct chan_centers {
|
||||
u16 ext_center;
|
||||
};
|
||||
|
||||
struct ath_rate_table;
|
||||
|
||||
/* Helpers */
|
||||
|
||||
enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
|
||||
@ -838,7 +829,7 @@ bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
u16 flags, u16 *low,
|
||||
u16 *high);
|
||||
u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
const struct ath9k_rate_table *rates,
|
||||
struct ath_rate_table *rates,
|
||||
u32 frameLen, u16 rateix,
|
||||
bool shortPreamble);
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
|
||||
@ -883,12 +874,6 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
|
||||
void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period);
|
||||
void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
|
||||
const struct ath9k_beacon_state *bs);
|
||||
|
||||
/* Rate table */
|
||||
|
||||
const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
|
||||
u32 mode);
|
||||
|
||||
/* HW Capabilities */
|
||||
|
||||
bool ath9k_hw_fill_cap_info(struct ath_hal *ah);
|
||||
@ -904,7 +889,7 @@ u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
|
||||
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
u32 ah_signal_type);
|
||||
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val);
|
||||
#ifdef CONFIG_RFKILL
|
||||
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
|
||||
void ath9k_enable_rfkill(struct ath_hal *ah);
|
||||
#endif
|
||||
int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg);
|
||||
|
@ -14,13 +14,9 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Implementation of beacon processing. */
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/*
|
||||
* Configure parameters for the beacon queue
|
||||
*
|
||||
* This function will modify certain transmit queue properties depending on
|
||||
* the operating mode of the station (AP or AdHoc). Parameters are AIFS
|
||||
* settings and channel width min/max
|
||||
@ -54,9 +50,15 @@ static int ath_beaconq_config(struct ath_softc *sc)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_bstuck_process(struct ath_softc *sc)
|
||||
{
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"%s: stuck beacon; resetting (bmiss count %u)\n",
|
||||
__func__, sc->sc_bmisscount);
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the beacon frame for transmit.
|
||||
*
|
||||
* Associates the beacon frame buffer with a transmit descriptor. Will set
|
||||
* up all required antenna switch parameters, rate codes, and channel flags.
|
||||
* Beacons are always sent out at the lowest rate, and are not retried.
|
||||
@ -68,7 +70,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_desc *ds;
|
||||
struct ath9k_11n_rate_series series[4];
|
||||
const struct ath9k_rate_table *rt;
|
||||
struct ath_rate_table *rt;
|
||||
int flags, antenna;
|
||||
u8 rix, rate;
|
||||
int ctsrate = 0;
|
||||
@ -106,10 +108,10 @@ static void ath_beacon_setup(struct ath_softc *sc,
|
||||
* XXX everything at min xmit rate
|
||||
*/
|
||||
rix = 0;
|
||||
rt = sc->sc_currates;
|
||||
rate = rt->info[rix].rateCode;
|
||||
rt = sc->hw_rate_table[sc->sc_curmode];
|
||||
rate = rt->info[rix].ratecode;
|
||||
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
|
||||
rate |= rt->info[rix].shortPreamble;
|
||||
rate |= rt->info[rix].short_preamble;
|
||||
|
||||
ath9k_hw_set11n_txdesc(ah, ds,
|
||||
skb->len + FCS_LEN, /* frame length */
|
||||
@ -138,14 +140,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
|
||||
ctsrate, ctsduration, series, 4, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate beacon frame and queue cab data for a vap.
|
||||
*
|
||||
* Updates the contents of the beacon frame. It is assumed that the buffer for
|
||||
* the beacon frame has been allocated in the ATH object, and simply needs to
|
||||
* be filled for this cycle. Also, any CAB (crap after beacon?) traffic will
|
||||
* be added to the beacon frame at this point.
|
||||
*/
|
||||
/* Generate beacon frame and queue cab data for a vap */
|
||||
static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
@ -275,14 +270,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
|
||||
sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a h/w transmit queue for beacons.
|
||||
*
|
||||
* This function allocates an information structure (struct ath9k_txq_info)
|
||||
* on the stack, sets some specific parameters (zero out channel width
|
||||
* min/max, and enable aifs). The info structure does not need to be
|
||||
* persistant.
|
||||
*/
|
||||
int ath_beaconq_setup(struct ath_hal *ah)
|
||||
{
|
||||
struct ath9k_tx_queue_info qi;
|
||||
@ -295,14 +282,6 @@ int ath_beaconq_setup(struct ath_hal *ah)
|
||||
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate and setup an initial beacon frame.
|
||||
*
|
||||
* Allocate a beacon state variable for a specific VAP instance created on
|
||||
* the ATH interface. This routine also calculates the beacon "slot" for
|
||||
* staggared beacons in the mBSSID case.
|
||||
*/
|
||||
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
@ -321,7 +300,6 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
if (!avp->av_bcbuf) {
|
||||
/* Allocate beacon state for hostap/ibss. We know
|
||||
* a buffer is available. */
|
||||
|
||||
avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
|
||||
struct ath_buf, list);
|
||||
list_del(&avp->av_bcbuf->list);
|
||||
@ -427,12 +405,6 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim beacon resources and return buffer to the pool.
|
||||
*
|
||||
* Checks the VAP to put the beacon frame buffer back to the ATH object
|
||||
* queue, and de-allocates any skbs that were sent as CAB traffic.
|
||||
*/
|
||||
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
|
||||
{
|
||||
if (avp->av_bcbuf != NULL) {
|
||||
@ -458,13 +430,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tasklet for Sending Beacons
|
||||
*
|
||||
* Transmit one or more beacon frames at SWBA. Dynamic updates to the frame
|
||||
* contents are done as needed and the slot time is also adjusted based on
|
||||
* current state.
|
||||
*/
|
||||
void ath9k_beacon_tasklet(unsigned long data)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
@ -481,9 +446,7 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
|
||||
if (sc->sc_flags & SC_OP_NO_RESET) {
|
||||
show_cycles = ath9k_hw_GetMibCycleCountsPct(ah,
|
||||
&rx_clear,
|
||||
&rx_frame,
|
||||
&tx_frame);
|
||||
&rx_clear, &rx_frame, &tx_frame);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -605,9 +568,10 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
if (sc->sc_updateslot == UPDATE) {
|
||||
sc->sc_updateslot = COMMIT; /* commit next beacon */
|
||||
sc->sc_slotupdate = slot;
|
||||
} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
|
||||
ath_setslottime(sc); /* commit change to hardware */
|
||||
|
||||
} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) {
|
||||
ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime);
|
||||
sc->sc_updateslot = OK;
|
||||
}
|
||||
if (bfaddr != 0) {
|
||||
/*
|
||||
* Stop any current dma and put the new frame(s) on the queue.
|
||||
@ -629,20 +593,6 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tasklet for Beacon Stuck processing
|
||||
*
|
||||
* Processing for Beacon Stuck.
|
||||
* Basically resets the chip.
|
||||
*/
|
||||
void ath_bstuck_process(struct ath_softc *sc)
|
||||
{
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"%s: stuck beacon; resetting (bmiss count %u)\n",
|
||||
__func__, sc->sc_bmisscount);
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the beacon and sleep timers.
|
||||
*
|
||||
@ -886,8 +836,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to collect beacon rssi data and resync beacon if necessary */
|
||||
|
||||
void ath_beacon_sync(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
/*
|
||||
|
@ -176,14 +176,14 @@ static bool getNoiseFloorThresh(struct ath_hal *ah,
|
||||
case CHANNEL_A_HT20:
|
||||
case CHANNEL_A_HT40PLUS:
|
||||
case CHANNEL_A_HT40MINUS:
|
||||
*nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
|
||||
*nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
|
||||
break;
|
||||
case CHANNEL_B:
|
||||
case CHANNEL_G:
|
||||
case CHANNEL_G_HT20:
|
||||
case CHANNEL_G_HT40PLUS:
|
||||
case CHANNEL_G_HT40MINUS:
|
||||
*nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
|
||||
*nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,10 +47,6 @@
|
||||
|
||||
struct ath_node;
|
||||
|
||||
/******************/
|
||||
/* Utility macros */
|
||||
/******************/
|
||||
|
||||
/* Macro to expand scalars to 64-bit objects */
|
||||
|
||||
#define ito64(x) (sizeof(x) == 8) ? \
|
||||
@ -86,11 +82,6 @@ struct ath_node;
|
||||
|
||||
#define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i))
|
||||
|
||||
static inline unsigned long get_timestamp(void)
|
||||
{
|
||||
return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ);
|
||||
}
|
||||
|
||||
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
/*************/
|
||||
@ -141,34 +132,6 @@ struct ath_config {
|
||||
u8 swBeaconProcess; /* Process received beacons in SW (vs HW) */
|
||||
};
|
||||
|
||||
/***********************/
|
||||
/* Chainmask Selection */
|
||||
/***********************/
|
||||
|
||||
#define ATH_CHAINMASK_SEL_TIMEOUT 6000
|
||||
/* Default - Number of last RSSI values that is used for
|
||||
* chainmask selection */
|
||||
#define ATH_CHAINMASK_SEL_RSSI_CNT 10
|
||||
/* Means use 3x3 chainmask instead of configured chainmask */
|
||||
#define ATH_CHAINMASK_SEL_3X3 7
|
||||
/* Default - Rssi threshold below which we have to switch to 3x3 */
|
||||
#define ATH_CHAINMASK_SEL_UP_RSSI_THRES 20
|
||||
/* Default - Rssi threshold above which we have to switch to
|
||||
* user configured values */
|
||||
#define ATH_CHAINMASK_SEL_DOWN_RSSI_THRES 35
|
||||
/* Struct to store the chainmask select related info */
|
||||
struct ath_chainmask_sel {
|
||||
struct timer_list timer;
|
||||
int cur_tx_mask; /* user configured or 3x3 */
|
||||
int cur_rx_mask; /* user configured or 3x3 */
|
||||
int tx_avgrssi;
|
||||
u8 switch_allowed:1, /* timer will set this */
|
||||
cm_sel_enabled : 1;
|
||||
};
|
||||
|
||||
int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an);
|
||||
void ath_update_chainmask(struct ath_softc *sc, int is_ht);
|
||||
|
||||
/*************************/
|
||||
/* Descriptor Management */
|
||||
/*************************/
|
||||
@ -203,7 +166,6 @@ struct ath_buf_state {
|
||||
int bfs_seqno; /* sequence number */
|
||||
int bfs_tidno; /* tid of this frame */
|
||||
int bfs_retries; /* current retries */
|
||||
struct ath_rc_series bfs_rcs[4]; /* rate series */
|
||||
u32 bf_type; /* BUF_* (enum buffer_type) */
|
||||
/* key type use to encrypt this frame */
|
||||
u32 bfs_keyix;
|
||||
@ -241,7 +203,6 @@ struct ath_buf {
|
||||
an aggregate) */
|
||||
struct ath_buf *bf_lastfrm; /* last buf of this frame */
|
||||
struct ath_buf *bf_next; /* next subframe in the aggregate */
|
||||
struct ath_buf *bf_rifslast; /* last buf for RIFS burst */
|
||||
void *bf_mpdu; /* enclosing frame structure */
|
||||
struct ath_desc *bf_desc; /* virtual addr of desc */
|
||||
dma_addr_t bf_daddr; /* physical addr of desc */
|
||||
@ -279,80 +240,27 @@ struct ath_descdma {
|
||||
dma_addr_t dd_dmacontext;
|
||||
};
|
||||
|
||||
/* Abstraction of a received RX MPDU/MMPDU, or a RX fragment */
|
||||
|
||||
struct ath_rx_context {
|
||||
struct ath_buf *ctx_rxbuf; /* associated ath_buf for rx */
|
||||
};
|
||||
#define ATH_RX_CONTEXT(skb) ((struct ath_rx_context *)skb->cb)
|
||||
|
||||
int ath_descdma_setup(struct ath_softc *sc,
|
||||
struct ath_descdma *dd,
|
||||
struct list_head *head,
|
||||
const char *name,
|
||||
int nbuf,
|
||||
int ndesc);
|
||||
int ath_desc_alloc(struct ath_softc *sc);
|
||||
void ath_desc_free(struct ath_softc *sc);
|
||||
void ath_descdma_cleanup(struct ath_softc *sc,
|
||||
struct ath_descdma *dd,
|
||||
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head, const char *name,
|
||||
int nbuf, int ndesc);
|
||||
void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head);
|
||||
|
||||
/******/
|
||||
/* RX */
|
||||
/******/
|
||||
/***********/
|
||||
/* RX / TX */
|
||||
/***********/
|
||||
|
||||
#define ATH_MAX_ANTENNA 3
|
||||
#define ATH_RXBUF 512
|
||||
#define WME_NUM_TID 16
|
||||
|
||||
/* per frame rx status block */
|
||||
struct ath_recv_status {
|
||||
u64 tsf; /* mac tsf */
|
||||
int8_t rssi; /* RSSI (noise floor ajusted) */
|
||||
int8_t rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
|
||||
int8_t rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
|
||||
int8_t abs_rssi; /* absolute RSSI */
|
||||
u8 rateieee; /* data rate received (IEEE rate code) */
|
||||
u8 ratecode; /* phy rate code */
|
||||
int rateKbps; /* data rate received (Kbps) */
|
||||
int antenna; /* rx antenna */
|
||||
int flags; /* status of associated skb */
|
||||
#define ATH_RX_FCS_ERROR 0x01
|
||||
#define ATH_RX_MIC_ERROR 0x02
|
||||
#define ATH_RX_DECRYPT_ERROR 0x04
|
||||
#define ATH_RX_RSSI_VALID 0x08
|
||||
/* if any of ctl,extn chainrssis are valid */
|
||||
#define ATH_RX_CHAIN_RSSI_VALID 0x10
|
||||
/* if extn chain rssis are valid */
|
||||
#define ATH_RX_RSSI_EXTN_VALID 0x20
|
||||
/* set if 40Mhz, clear if 20Mhz */
|
||||
#define ATH_RX_40MHZ 0x40
|
||||
/* set if short GI, clear if full GI */
|
||||
#define ATH_RX_SHORT_GI 0x80
|
||||
};
|
||||
|
||||
struct ath_rxbuf {
|
||||
struct sk_buff *rx_wbuf;
|
||||
unsigned long rx_time; /* system time when received */
|
||||
struct ath_recv_status rx_status; /* cached rx status */
|
||||
};
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
||||
bool ath_stoprecv(struct ath_softc *sc);
|
||||
void ath_flushrecv(struct ath_softc *sc);
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
||||
void ath_handle_rx_intr(struct ath_softc *sc);
|
||||
int ath_rx_init(struct ath_softc *sc, int nbufs);
|
||||
void ath_rx_cleanup(struct ath_softc *sc);
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush);
|
||||
int _ath_rx_indicate(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
struct ath_recv_status *status,
|
||||
u16 keyix);
|
||||
/******/
|
||||
/* TX */
|
||||
/******/
|
||||
|
||||
#define ATH_TXBUF 512
|
||||
/* max number of transmit attempts (tries) */
|
||||
@ -500,9 +408,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
|
||||
void ath_tx_tasklet(struct ath_softc *sc);
|
||||
u32 ath_txq_depth(struct ath_softc *sc, int qnum);
|
||||
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
|
||||
void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
|
||||
void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_xmit_status *tx_status);
|
||||
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
|
||||
|
||||
/**********************/
|
||||
@ -567,25 +472,41 @@ struct ath_node_aggr {
|
||||
/* driver-specific node state */
|
||||
struct ath_node {
|
||||
struct ath_softc *an_sc;
|
||||
struct ath_chainmask_sel an_chainmask_sel;
|
||||
struct ath_node_aggr an_aggr;
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
};
|
||||
|
||||
void ath_tx_resume_tid(struct ath_softc *sc,
|
||||
struct ath_atx_tid *tid);
|
||||
void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
|
||||
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
|
||||
void ath_tx_aggr_teardown(struct ath_softc *sc,
|
||||
struct ath_node *an, u8 tidno);
|
||||
void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tidno);
|
||||
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
u16 tid, u16 *ssn);
|
||||
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
void ath_newassoc(struct ath_softc *sc,
|
||||
struct ath_node *node, int isnew, int isuapsd);
|
||||
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
|
||||
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
|
||||
|
||||
/********/
|
||||
/* VAPs */
|
||||
/********/
|
||||
|
||||
/*
|
||||
* Define the scheme that we select MAC address for multiple
|
||||
* BSS on the same radio. The very first VAP will just use the MAC
|
||||
* address from the EEPROM. For the next 3 VAPs, we set the
|
||||
* U/L bit (bit 1) in MAC address, and use the next two bits as the
|
||||
* index of the VAP.
|
||||
*/
|
||||
|
||||
#define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
|
||||
((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))
|
||||
|
||||
/* driver-specific vap state */
|
||||
struct ath_vap {
|
||||
int av_bslot; /* beacon slot index */
|
||||
enum ath9k_opmode av_opmode; /* VAP operational mode */
|
||||
struct ath_buf *av_bcbuf; /* beacon buffer */
|
||||
struct ath_tx_control av_btxctl; /* txctl information for beacon */
|
||||
};
|
||||
|
||||
/*******************/
|
||||
/* Beacon Handling */
|
||||
@ -620,80 +541,8 @@ void ath9k_beacon_tasklet(unsigned long data);
|
||||
void ath_beacon_config(struct ath_softc *sc, int if_id);
|
||||
int ath_beaconq_setup(struct ath_hal *ah);
|
||||
int ath_beacon_alloc(struct ath_softc *sc, int if_id);
|
||||
void ath_bstuck_process(struct ath_softc *sc);
|
||||
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp);
|
||||
void ath_beacon_sync(struct ath_softc *sc, int if_id);
|
||||
void ath_get_beaconconfig(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ath_beacon_config *conf);
|
||||
/********/
|
||||
/* VAPs */
|
||||
/********/
|
||||
|
||||
/*
|
||||
* Define the scheme that we select MAC address for multiple
|
||||
* BSS on the same radio. The very first VAP will just use the MAC
|
||||
* address from the EEPROM. For the next 3 VAPs, we set the
|
||||
* U/L bit (bit 1) in MAC address, and use the next two bits as the
|
||||
* index of the VAP.
|
||||
*/
|
||||
|
||||
#define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
|
||||
((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))
|
||||
|
||||
/* VAP configuration (from protocol layer) */
|
||||
struct ath_vap_config {
|
||||
u32 av_fixed_rateset;
|
||||
u32 av_fixed_retryset;
|
||||
};
|
||||
|
||||
/* driver-specific vap state */
|
||||
struct ath_vap {
|
||||
int av_bslot; /* beacon slot index */
|
||||
enum ath9k_opmode av_opmode; /* VAP operational mode */
|
||||
struct ath_buf *av_bcbuf; /* beacon buffer */
|
||||
struct ath_tx_control av_btxctl; /* txctl information for beacon */
|
||||
struct ath_vap_config av_config;/* vap configuration parameters*/
|
||||
struct ath_rate_node *rc_node;
|
||||
};
|
||||
|
||||
/*********************/
|
||||
/* Antenna diversity */
|
||||
/*********************/
|
||||
|
||||
#define ATH_ANT_DIV_MAX_CFG 2
|
||||
#define ATH_ANT_DIV_MIN_IDLE_US 1000000 /* us */
|
||||
#define ATH_ANT_DIV_MIN_SCAN_US 50000 /* us */
|
||||
|
||||
enum ATH_ANT_DIV_STATE{
|
||||
ATH_ANT_DIV_IDLE,
|
||||
ATH_ANT_DIV_SCAN, /* evaluating antenna */
|
||||
};
|
||||
|
||||
struct ath_antdiv {
|
||||
struct ath_softc *antdiv_sc;
|
||||
u8 antdiv_start;
|
||||
enum ATH_ANT_DIV_STATE antdiv_state;
|
||||
u8 antdiv_num_antcfg;
|
||||
u8 antdiv_curcfg;
|
||||
u8 antdiv_bestcfg;
|
||||
int32_t antdivf_rssitrig;
|
||||
int32_t antdiv_lastbrssi[ATH_ANT_DIV_MAX_CFG];
|
||||
u64 antdiv_lastbtsf[ATH_ANT_DIV_MAX_CFG];
|
||||
u64 antdiv_laststatetsf;
|
||||
u8 antdiv_bssid[ETH_ALEN];
|
||||
};
|
||||
|
||||
void ath_slow_ant_div_init(struct ath_antdiv *antdiv,
|
||||
struct ath_softc *sc, int32_t rssitrig);
|
||||
void ath_slow_ant_div_start(struct ath_antdiv *antdiv,
|
||||
u8 num_antcfg,
|
||||
const u8 *bssid);
|
||||
void ath_slow_ant_div_stop(struct ath_antdiv *antdiv);
|
||||
void ath_slow_ant_div(struct ath_antdiv *antdiv,
|
||||
struct ieee80211_hdr *wh,
|
||||
struct ath_rx_status *rx_stats);
|
||||
void ath_setdefantenna(void *sc, u32 antenna);
|
||||
|
||||
/*******/
|
||||
/* ANI */
|
||||
@ -775,30 +624,8 @@ struct ath_rfkill {
|
||||
|
||||
#define ATH_IF_ID_ANY 0xff
|
||||
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
|
||||
|
||||
#define RSSI_LPF_THRESHOLD -20
|
||||
#define ATH_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */
|
||||
#define ATH_RATE_DUMMY_MARKER 0
|
||||
#define ATH_RSSI_LPF_LEN 10
|
||||
#define ATH_RSSI_DUMMY_MARKER 0x127
|
||||
|
||||
#define ATH_EP_MUL(x, mul) ((x) * (mul))
|
||||
#define ATH_EP_RND(x, mul) \
|
||||
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
|
||||
#define ATH_RSSI_OUT(x) \
|
||||
(((x) != ATH_RSSI_DUMMY_MARKER) ? \
|
||||
(ATH_EP_RND((x), ATH_RSSI_EP_MULTIPLIER)) : ATH_RSSI_DUMMY_MARKER)
|
||||
#define ATH_RSSI_IN(x) \
|
||||
(ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
|
||||
#define ATH_LPF_RSSI(x, y, len) \
|
||||
((x != ATH_RSSI_DUMMY_MARKER) ? \
|
||||
(((x) * ((len) - 1) + (y)) / (len)) : (y))
|
||||
#define ATH_RSSI_LPF(x, y) do { \
|
||||
if ((y) >= RSSI_LPF_THRESHOLD) \
|
||||
x = ATH_LPF_RSSI((x), \
|
||||
ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
|
||||
} while (0)
|
||||
|
||||
#define ATH_RSSI_DUMMY_MARKER 0x127
|
||||
#define ATH_RATE_DUMMY_MARKER 0
|
||||
|
||||
enum PROT_MODE {
|
||||
PROT_M_NONE = 0,
|
||||
@ -806,17 +633,6 @@ enum PROT_MODE {
|
||||
PROT_M_CTSONLY
|
||||
};
|
||||
|
||||
enum RATE_TYPE {
|
||||
NORMAL_RATE = 0,
|
||||
HALF_RATE,
|
||||
QUARTER_RATE
|
||||
};
|
||||
|
||||
struct ath_ht_info {
|
||||
enum ath9k_ht_macmode tx_chan_width;
|
||||
u8 ext_chan_offset;
|
||||
};
|
||||
|
||||
#define SC_OP_INVALID BIT(0)
|
||||
#define SC_OP_BEACONS BIT(1)
|
||||
#define SC_OP_RXAGGR BIT(2)
|
||||
@ -839,7 +655,6 @@ struct ath_softc {
|
||||
struct tasklet_struct bcon_tasklet;
|
||||
struct ath_config sc_config;
|
||||
struct ath_hal *sc_ah;
|
||||
struct ath_rate_softc *sc_rc;
|
||||
void __iomem *mem;
|
||||
|
||||
u8 sc_curbssid[ETH_ALEN];
|
||||
@ -871,8 +686,8 @@ struct ath_softc {
|
||||
u8 sc_rxotherant; /* rx's on non-default antenna */
|
||||
|
||||
struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
|
||||
struct ath_ht_info sc_ht_info;
|
||||
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
|
||||
enum ath9k_ht_macmode tx_chan_width;
|
||||
|
||||
#ifdef CONFIG_SLOW_ANT_DIV
|
||||
struct ath_antdiv sc_antdiv;
|
||||
@ -914,13 +729,8 @@ struct ath_softc {
|
||||
|
||||
/* Rate */
|
||||
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
|
||||
const struct ath9k_rate_table *sc_currates;
|
||||
u8 sc_rixmap[256]; /* IEEE to h/w rate table ix */
|
||||
struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
|
||||
u8 sc_protrix; /* protection rate index */
|
||||
struct {
|
||||
u32 rateKbps; /* transfer rate in kbs */
|
||||
u8 ieeerate; /* IEEE rate */
|
||||
} sc_hwmap[256]; /* h/w rate ix mappings */
|
||||
|
||||
/* Channel, Band */
|
||||
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
|
||||
@ -945,27 +755,9 @@ struct ath_softc {
|
||||
struct ath_ani sc_ani;
|
||||
};
|
||||
|
||||
int ath_init(u16 devid, struct ath_softc *sc);
|
||||
int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
|
||||
void ath_stop(struct ath_softc *sc);
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
int ath_reset(struct ath_softc *sc, bool retry_tx);
|
||||
int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
|
||||
|
||||
/*********************/
|
||||
/* Utility Functions */
|
||||
/*********************/
|
||||
|
||||
void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot);
|
||||
int ath_keyset(struct ath_softc *sc,
|
||||
u16 keyix,
|
||||
struct ath9k_keyval *hk,
|
||||
const u8 mac[ETH_ALEN]);
|
||||
int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
|
||||
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
|
||||
void ath_setslottime(struct ath_softc *sc);
|
||||
void ath_update_txpow(struct ath_softc *sc);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
|
||||
|
||||
#endif /* CORE_H */
|
||||
|
@ -1244,7 +1244,7 @@ bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
|
||||
|
||||
txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
|
||||
|
||||
ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 1, &ant_config);
|
||||
ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
|
||||
REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
@ -1551,9 +1551,9 @@ u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
|
||||
|
||||
switch (param) {
|
||||
case EEP_NFTHRESH_5:
|
||||
return -pModal[0].noiseFloorThreshCh[0];
|
||||
return pModal[0].noiseFloorThreshCh[0];
|
||||
case EEP_NFTHRESH_2:
|
||||
return -pModal[1].noiseFloorThreshCh[0];
|
||||
return pModal[1].noiseFloorThreshCh[0];
|
||||
case AR_EEPROM_MAC(0):
|
||||
return pBase->macAddr[0] << 8 | pBase->macAddr[1];
|
||||
case AR_EEPROM_MAC(1):
|
||||
@ -1584,6 +1584,11 @@ u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
|
||||
return pBase->txMask;
|
||||
case EEP_RX_MASK:
|
||||
return pBase->rxMask;
|
||||
case EEP_RXGAIN_TYPE:
|
||||
return pBase->rxGainType;
|
||||
case EEP_TXGAIN_TYPE:
|
||||
return pBase->txGainType;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,10 +86,11 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
|
||||
enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
|
||||
const struct ath9k_channel *chan)
|
||||
{
|
||||
if (IS_CHAN_CCK(chan))
|
||||
return ATH9K_MODE_11A;
|
||||
if (IS_CHAN_B(chan))
|
||||
return ATH9K_MODE_11B;
|
||||
if (IS_CHAN_G(chan))
|
||||
return ATH9K_MODE_11G;
|
||||
|
||||
return ATH9K_MODE_11A;
|
||||
}
|
||||
|
||||
@ -142,27 +143,27 @@ bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
}
|
||||
|
||||
u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
const struct ath9k_rate_table *rates,
|
||||
struct ath_rate_table *rates,
|
||||
u32 frameLen, u16 rateix,
|
||||
bool shortPreamble)
|
||||
{
|
||||
u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
|
||||
u32 kbps;
|
||||
|
||||
kbps = rates->info[rateix].rateKbps;
|
||||
kbps = rates->info[rateix].ratekbps;
|
||||
|
||||
if (kbps == 0)
|
||||
return 0;
|
||||
|
||||
switch (rates->info[rateix].phy) {
|
||||
case PHY_CCK:
|
||||
case WLAN_RC_PHY_CCK:
|
||||
phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
|
||||
if (shortPreamble && rates->info[rateix].shortPreamble)
|
||||
if (shortPreamble && rates->info[rateix].short_preamble)
|
||||
phyTime >>= 1;
|
||||
numBits = frameLen << 3;
|
||||
txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
|
||||
break;
|
||||
case PHY_OFDM:
|
||||
case WLAN_RC_PHY_OFDM:
|
||||
if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
|
||||
bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
|
||||
numBits = OFDM_PLCP_BITS + (frameLen << 3);
|
||||
@ -557,6 +558,54 @@ static int ath9k_hw_init_macaddr(struct ath_hal *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_init_rxgain_ini(struct ath_hal *ah)
|
||||
{
|
||||
u32 rxgain_type;
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
|
||||
rxgain_type = ath9k_hw_get_eeprom(ah, EEP_RXGAIN_TYPE);
|
||||
|
||||
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
|
||||
ar9280Modes_backoff_13db_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
|
||||
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
|
||||
ar9280Modes_backoff_23db_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
|
||||
else
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
|
||||
ar9280Modes_original_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
|
||||
} else
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
|
||||
ar9280Modes_original_rxgain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
|
||||
}
|
||||
|
||||
static void ath9k_hw_init_txgain_ini(struct ath_hal *ah)
|
||||
{
|
||||
u32 txgain_type;
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
|
||||
txgain_type = ath9k_hw_get_eeprom(ah, EEP_TXGAIN_TYPE);
|
||||
|
||||
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
|
||||
ar9280Modes_high_power_tx_gain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
|
||||
else
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
|
||||
ar9280Modes_original_tx_gain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
|
||||
} else
|
||||
INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
|
||||
ar9280Modes_original_tx_gain_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
|
||||
}
|
||||
|
||||
static int ath9k_hw_post_attach(struct ath_hal *ah)
|
||||
{
|
||||
int ecode;
|
||||
@ -800,6 +849,14 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
|
||||
if (ecode != 0)
|
||||
goto bad;
|
||||
|
||||
/* rxgain table */
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ath9k_hw_init_rxgain_ini(ah);
|
||||
|
||||
/* txgain table */
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ath9k_hw_init_txgain_ini(ah);
|
||||
|
||||
#ifndef CONFIG_SLOW_ANT_DIV
|
||||
if (ah->ah_devid == AR9280_DEVID_PCI) {
|
||||
for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
|
||||
@ -853,7 +910,7 @@ static void ath9k_hw_init_bb(struct ath_hal *ah,
|
||||
u32 synthDelay;
|
||||
|
||||
synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
|
||||
if (IS_CHAN_CCK(chan))
|
||||
if (IS_CHAN_B(chan))
|
||||
synthDelay = (4 * synthDelay) / 22;
|
||||
else
|
||||
synthDelay /= 10;
|
||||
@ -1258,6 +1315,12 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
|
||||
DO_DELAY(regWrites);
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
REG_WRITE_ARRAY(&ahp->ah_iniModesRxGain, modesIndex, regWrites);
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
REG_WRITE_ARRAY(&ahp->ah_iniModesTxGain, modesIndex, regWrites);
|
||||
|
||||
for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
|
||||
u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0);
|
||||
u32 val = INI_RA(&ahp->ah_iniCommon, i, 1);
|
||||
@ -1585,7 +1648,7 @@ static struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
|
||||
}
|
||||
|
||||
if (!IS_CHAN_OFDM(chan) &&
|
||||
!IS_CHAN_CCK(chan) &&
|
||||
!IS_CHAN_B(chan) &&
|
||||
!IS_CHAN_HT20(chan) &&
|
||||
!IS_CHAN_HT40(chan)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
@ -1649,7 +1712,7 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah,
|
||||
}
|
||||
|
||||
synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
|
||||
if (IS_CHAN_CCK(chan))
|
||||
if (IS_CHAN_B(chan))
|
||||
synthDelay = (4 * synthDelay) / 22;
|
||||
else
|
||||
synthDelay /= 10;
|
||||
@ -2169,8 +2232,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
((chan->channelFlags & CHANNEL_ALL) ==
|
||||
(ah->ah_curchan->channelFlags & CHANNEL_ALL)) &&
|
||||
(!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
|
||||
!IS_CHAN_A_5MHZ_SPACED(ah->
|
||||
ah_curchan)))) {
|
||||
!IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) {
|
||||
|
||||
if (ath9k_hw_channel_change(ah, chan, macmode)) {
|
||||
ath9k_hw_loadnf(ah, ah->ah_curchan);
|
||||
@ -2278,7 +2340,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
|
||||
ath9k_hw_init_qos(ah);
|
||||
|
||||
#ifdef CONFIG_RFKILL
|
||||
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
|
||||
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
|
||||
ath9k_enable_rfkill(ah);
|
||||
#endif
|
||||
@ -3128,190 +3190,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
|
||||
|
||||
}
|
||||
|
||||
/***************/
|
||||
/* Rate tables */
|
||||
/***************/
|
||||
|
||||
static struct ath9k_rate_table ar5416_11a_table = {
|
||||
8,
|
||||
{0},
|
||||
{
|
||||
{true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
|
||||
{true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
|
||||
{true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
|
||||
{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
|
||||
{true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
|
||||
{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
|
||||
{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
|
||||
{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}
|
||||
},
|
||||
};
|
||||
|
||||
static struct ath9k_rate_table ar5416_11b_table = {
|
||||
4,
|
||||
{0},
|
||||
{
|
||||
{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
|
||||
{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
|
||||
{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1},
|
||||
{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1}
|
||||
},
|
||||
};
|
||||
|
||||
static struct ath9k_rate_table ar5416_11g_table = {
|
||||
12,
|
||||
{0},
|
||||
{
|
||||
{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
|
||||
{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
|
||||
{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
|
||||
{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
|
||||
|
||||
{false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
|
||||
{false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
|
||||
{true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
|
||||
{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
|
||||
{true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
|
||||
{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
|
||||
{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
|
||||
{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}
|
||||
},
|
||||
};
|
||||
|
||||
static struct ath9k_rate_table ar5416_11ng_table = {
|
||||
28,
|
||||
{0},
|
||||
{
|
||||
{true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
|
||||
{true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
|
||||
{true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
|
||||
{true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
|
||||
|
||||
{false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
|
||||
{false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
|
||||
{true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
|
||||
{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
|
||||
{true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
|
||||
{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
|
||||
{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
|
||||
{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8},
|
||||
{true, PHY_HT, 6500, 0x80, 0x00, 0, 4},
|
||||
{true, PHY_HT, 13000, 0x81, 0x00, 1, 6},
|
||||
{true, PHY_HT, 19500, 0x82, 0x00, 2, 6},
|
||||
{true, PHY_HT, 26000, 0x83, 0x00, 3, 8},
|
||||
{true, PHY_HT, 39000, 0x84, 0x00, 4, 8},
|
||||
{true, PHY_HT, 52000, 0x85, 0x00, 5, 8},
|
||||
{true, PHY_HT, 58500, 0x86, 0x00, 6, 8},
|
||||
{true, PHY_HT, 65000, 0x87, 0x00, 7, 8},
|
||||
{true, PHY_HT, 13000, 0x88, 0x00, 8, 4},
|
||||
{true, PHY_HT, 26000, 0x89, 0x00, 9, 6},
|
||||
{true, PHY_HT, 39000, 0x8a, 0x00, 10, 6},
|
||||
{true, PHY_HT, 52000, 0x8b, 0x00, 11, 8},
|
||||
{true, PHY_HT, 78000, 0x8c, 0x00, 12, 8},
|
||||
{true, PHY_HT, 104000, 0x8d, 0x00, 13, 8},
|
||||
{true, PHY_HT, 117000, 0x8e, 0x00, 14, 8},
|
||||
{true, PHY_HT, 130000, 0x8f, 0x00, 15, 8},
|
||||
},
|
||||
};
|
||||
|
||||
static struct ath9k_rate_table ar5416_11na_table = {
|
||||
24,
|
||||
{0},
|
||||
{
|
||||
{true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
|
||||
{true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
|
||||
{true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
|
||||
{true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
|
||||
{true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
|
||||
{true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
|
||||
{true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
|
||||
{true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4},
|
||||
{true, PHY_HT, 6500, 0x80, 0x00, 0, 0},
|
||||
{true, PHY_HT, 13000, 0x81, 0x00, 1, 2},
|
||||
{true, PHY_HT, 19500, 0x82, 0x00, 2, 2},
|
||||
{true, PHY_HT, 26000, 0x83, 0x00, 3, 4},
|
||||
{true, PHY_HT, 39000, 0x84, 0x00, 4, 4},
|
||||
{true, PHY_HT, 52000, 0x85, 0x00, 5, 4},
|
||||
{true, PHY_HT, 58500, 0x86, 0x00, 6, 4},
|
||||
{true, PHY_HT, 65000, 0x87, 0x00, 7, 4},
|
||||
{true, PHY_HT, 13000, 0x88, 0x00, 8, 0},
|
||||
{true, PHY_HT, 26000, 0x89, 0x00, 9, 2},
|
||||
{true, PHY_HT, 39000, 0x8a, 0x00, 10, 2},
|
||||
{true, PHY_HT, 52000, 0x8b, 0x00, 11, 4},
|
||||
{true, PHY_HT, 78000, 0x8c, 0x00, 12, 4},
|
||||
{true, PHY_HT, 104000, 0x8d, 0x00, 13, 4},
|
||||
{true, PHY_HT, 117000, 0x8e, 0x00, 14, 4},
|
||||
{true, PHY_HT, 130000, 0x8f, 0x00, 15, 4},
|
||||
},
|
||||
};
|
||||
|
||||
static void ath9k_hw_setup_rate_table(struct ath_hal *ah,
|
||||
struct ath9k_rate_table *rt)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (rt->rateCodeToIndex[0] != 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
rt->rateCodeToIndex[i] = (u8) -1;
|
||||
|
||||
for (i = 0; i < rt->rateCount; i++) {
|
||||
u8 code = rt->info[i].rateCode;
|
||||
u8 cix = rt->info[i].controlRate;
|
||||
|
||||
rt->rateCodeToIndex[code] = i;
|
||||
rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
|
||||
|
||||
rt->info[i].lpAckDuration =
|
||||
ath9k_hw_computetxtime(ah, rt,
|
||||
WLAN_CTRL_FRAME_SIZE,
|
||||
cix,
|
||||
false);
|
||||
rt->info[i].spAckDuration =
|
||||
ath9k_hw_computetxtime(ah, rt,
|
||||
WLAN_CTRL_FRAME_SIZE,
|
||||
cix,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
|
||||
u32 mode)
|
||||
{
|
||||
struct ath9k_rate_table *rt;
|
||||
|
||||
switch (mode) {
|
||||
case ATH9K_MODE_11A:
|
||||
rt = &ar5416_11a_table;
|
||||
break;
|
||||
case ATH9K_MODE_11B:
|
||||
rt = &ar5416_11b_table;
|
||||
break;
|
||||
case ATH9K_MODE_11G:
|
||||
rt = &ar5416_11g_table;
|
||||
break;
|
||||
case ATH9K_MODE_11NG_HT20:
|
||||
case ATH9K_MODE_11NG_HT40PLUS:
|
||||
case ATH9K_MODE_11NG_HT40MINUS:
|
||||
rt = &ar5416_11ng_table;
|
||||
break;
|
||||
case ATH9K_MODE_11NA_HT20:
|
||||
case ATH9K_MODE_11NA_HT40PLUS:
|
||||
case ATH9K_MODE_11NA_HT40MINUS:
|
||||
rt = &ar5416_11na_table;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n",
|
||||
__func__, mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ath9k_hw_setup_rate_table(ah, rt);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/* HW Capabilities */
|
||||
/*******************/
|
||||
@ -3453,7 +3331,7 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
|
||||
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
|
||||
|
||||
#ifdef CONFIG_RFKILL
|
||||
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
|
||||
ah->ah_rfsilent = ath9k_hw_get_eeprom(ah, EEP_RF_SILENT);
|
||||
if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
|
||||
ah->ah_rfkill_gpio =
|
||||
@ -3710,7 +3588,7 @@ void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
|
||||
AR_GPIO_BIT(gpio));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFKILL
|
||||
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
|
||||
void ath9k_enable_rfkill(struct ath_hal *ah)
|
||||
{
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
|
@ -415,6 +415,9 @@ struct ar5416Stats {
|
||||
#define AR5416_EEP_MINOR_VER_3 0x3
|
||||
#define AR5416_EEP_MINOR_VER_7 0x7
|
||||
#define AR5416_EEP_MINOR_VER_9 0x9
|
||||
#define AR5416_EEP_MINOR_VER_16 0x10
|
||||
#define AR5416_EEP_MINOR_VER_17 0x11
|
||||
#define AR5416_EEP_MINOR_VER_19 0x13
|
||||
|
||||
#define AR5416_NUM_5G_CAL_PIERS 8
|
||||
#define AR5416_NUM_2G_CAL_PIERS 4
|
||||
@ -436,6 +439,16 @@ struct ar5416Stats {
|
||||
#define AR5416_MAX_CHAINS 3
|
||||
#define AR5416_PWR_TABLE_OFFSET -5
|
||||
|
||||
/* Rx gain type values */
|
||||
#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
|
||||
#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
|
||||
#define AR5416_EEP_RXGAIN_ORIG 2
|
||||
|
||||
/* Tx gain type values */
|
||||
#define AR5416_EEP_TXGAIN_ORIGINAL 0
|
||||
#define AR5416_EEP_TXGAIN_HIGH_POWER 1
|
||||
|
||||
|
||||
enum eeprom_param {
|
||||
EEP_NFTHRESH_5,
|
||||
EEP_NFTHRESH_2,
|
||||
@ -454,6 +467,8 @@ enum eeprom_param {
|
||||
EEP_MINOR_REV,
|
||||
EEP_TX_MASK,
|
||||
EEP_RX_MASK,
|
||||
EEP_RXGAIN_TYPE,
|
||||
EEP_TXGAIN_TYPE,
|
||||
};
|
||||
|
||||
enum ar5416_rates {
|
||||
@ -485,7 +500,11 @@ struct base_eep_header {
|
||||
u32 binBuildNumber;
|
||||
u8 deviceType;
|
||||
u8 pwdclkind;
|
||||
u8 futureBase[32];
|
||||
u8 futureBase_1[2];
|
||||
u8 rxGainType;
|
||||
u8 futureBase_2[3];
|
||||
u8 txGainType;
|
||||
u8 futureBase_3[25];
|
||||
} __packed;
|
||||
|
||||
struct spur_chan {
|
||||
@ -792,6 +811,8 @@ struct ath_hal_5416 {
|
||||
struct ar5416IniArray ah_iniAddac;
|
||||
struct ar5416IniArray ah_iniPcieSerdes;
|
||||
struct ar5416IniArray ah_iniModesAdditional;
|
||||
struct ar5416IniArray ah_iniModesRxGain;
|
||||
struct ar5416IniArray ah_iniModesTxGain;
|
||||
};
|
||||
#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah))
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* AR5416 to Fowl ar5146.ini */
|
||||
static const u32 ar5416Modes_9100[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
@ -31,17 +32,17 @@ static const u32 ar5416Modes_9100[][6] = {
|
||||
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x00009850, 0x6de8b4e0, 0x6de8b4e0, 0x6de8b0de, 0x6de8b0de, 0x6de8b0de },
|
||||
{ 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de },
|
||||
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
|
||||
{ 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
|
||||
{ 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
|
||||
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
|
||||
{ 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 },
|
||||
{ 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b },
|
||||
{ 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
|
||||
{ 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
|
||||
{ 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
|
||||
{ 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
|
||||
{ 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
|
||||
@ -207,7 +208,7 @@ static const u32 ar5416Common_9100[][2] = {
|
||||
{ 0x00008134, 0x00000000 },
|
||||
{ 0x00008138, 0x00000000 },
|
||||
{ 0x0000813c, 0x00000000 },
|
||||
{ 0x00008144, 0x00000000 },
|
||||
{ 0x00008144, 0xffffffff },
|
||||
{ 0x00008168, 0x00000000 },
|
||||
{ 0x0000816c, 0x00000000 },
|
||||
{ 0x00008170, 0x32143320 },
|
||||
@ -266,7 +267,7 @@ static const u32 ar5416Common_9100[][2] = {
|
||||
{ 0x0000832c, 0x00000007 },
|
||||
{ 0x00008330, 0x00000302 },
|
||||
{ 0x00008334, 0x00000e00 },
|
||||
{ 0x00008338, 0x00000000 },
|
||||
{ 0x00008338, 0x00070000 },
|
||||
{ 0x0000833c, 0x00000000 },
|
||||
{ 0x00008340, 0x000107ff },
|
||||
{ 0x00009808, 0x00000000 },
|
||||
@ -661,6 +662,7 @@ static const u32 ar5416Addac_9100[][2] = {
|
||||
{0x000098c4, 0x00000000 },
|
||||
};
|
||||
|
||||
/* ar5416 - howl ar5416_howl.ini */
|
||||
static const u32 ar5416Modes[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
@ -952,7 +954,7 @@ static const u32 ar5416Common[][2] = {
|
||||
{ 0x0000994c, 0x00020028 },
|
||||
{ 0x0000c95c, 0x004b6a8e },
|
||||
{ 0x0000c968, 0x000003ce },
|
||||
{ 0x00009970, 0x190fb514 },
|
||||
{ 0x00009970, 0x190fb515 },
|
||||
{ 0x00009974, 0x00000000 },
|
||||
{ 0x00009978, 0x00000001 },
|
||||
{ 0x0000997c, 0x00000000 },
|
||||
@ -1311,7 +1313,7 @@ static const u32 ar5416Addac[][2] = {
|
||||
{0x000098cc, 0x00000000 },
|
||||
};
|
||||
|
||||
|
||||
/* AR5416 9160 Sowl ar5416_sowl.ini */
|
||||
static const u32 ar5416Modes_9160[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
@ -1329,21 +1331,22 @@ static const u32 ar5416Modes_9160[][6] = {
|
||||
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
|
||||
{ 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 },
|
||||
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
|
||||
{ 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
|
||||
{ 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
|
||||
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
|
||||
{ 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
|
||||
{ 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
|
||||
{ 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
|
||||
{ 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
|
||||
{ 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
|
||||
{ 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
|
||||
{ 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
|
||||
{ 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
|
||||
{ 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
|
||||
{ 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
|
||||
{ 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
|
||||
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
|
||||
@ -1505,7 +1508,7 @@ static const u32 ar5416Common_9160[][2] = {
|
||||
{ 0x00008134, 0x00000000 },
|
||||
{ 0x00008138, 0x00000000 },
|
||||
{ 0x0000813c, 0x00000000 },
|
||||
{ 0x00008144, 0x00000000 },
|
||||
{ 0x00008144, 0xffffffff },
|
||||
{ 0x00008168, 0x00000000 },
|
||||
{ 0x0000816c, 0x00000000 },
|
||||
{ 0x00008170, 0x32143320 },
|
||||
@ -1564,7 +1567,7 @@ static const u32 ar5416Common_9160[][2] = {
|
||||
{ 0x0000832c, 0x00000007 },
|
||||
{ 0x00008330, 0x00000302 },
|
||||
{ 0x00008334, 0x00000e00 },
|
||||
{ 0x00008338, 0x00000000 },
|
||||
{ 0x00008338, 0x00ff0000 },
|
||||
{ 0x0000833c, 0x00000000 },
|
||||
{ 0x00008340, 0x000107ff },
|
||||
{ 0x00009808, 0x00000000 },
|
||||
@ -1597,7 +1600,6 @@ static const u32 ar5416Common_9160[][2] = {
|
||||
{ 0x00009958, 0x2108ecff },
|
||||
{ 0x00009940, 0x00750604 },
|
||||
{ 0x0000c95c, 0x004b6a8e },
|
||||
{ 0x0000c968, 0x000003ce },
|
||||
{ 0x00009970, 0x190fb515 },
|
||||
{ 0x00009974, 0x00000000 },
|
||||
{ 0x00009978, 0x00000001 },
|
||||
@ -1699,7 +1701,7 @@ static const u32 ar5416Common_9160[][2] = {
|
||||
{ 0x0000a244, 0x00007bb6 },
|
||||
{ 0x0000a248, 0x0fff3ffc },
|
||||
{ 0x0000a24c, 0x00000001 },
|
||||
{ 0x0000a250, 0x0000a000 },
|
||||
{ 0x0000a250, 0x0000e000 },
|
||||
{ 0x0000a254, 0x00000000 },
|
||||
{ 0x0000a258, 0x0cc75380 },
|
||||
{ 0x0000a25c, 0x0f0f0f01 },
|
||||
@ -1719,7 +1721,7 @@ static const u32 ar5416Common_9160[][2] = {
|
||||
{ 0x0000a34c, 0x3fffffff },
|
||||
{ 0x0000a350, 0x3fffffff },
|
||||
{ 0x0000a354, 0x0003ffff },
|
||||
{ 0x0000a358, 0x79a8aa33 },
|
||||
{ 0x0000a358, 0x79bfaa03 },
|
||||
{ 0x0000d35c, 0x07ffffef },
|
||||
{ 0x0000d360, 0x0fffffe7 },
|
||||
{ 0x0000d364, 0x17ffffe5 },
|
||||
@ -1842,7 +1844,6 @@ static const u32 ar5416Bank3_9160[][3] = {
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6_9160[][3] = {
|
||||
|
||||
{ 0x0000989c, 0x00000000, 0x00000000 },
|
||||
{ 0x0000989c, 0x00000000, 0x00000000 },
|
||||
{ 0x0000989c, 0x00000000, 0x00000000 },
|
||||
@ -1920,7 +1921,6 @@ static const u32 ar5416Bank7_9160[][2] = {
|
||||
{ 0x000098cc, 0x0000000e },
|
||||
};
|
||||
|
||||
|
||||
static u32 ar5416Addac_9160[][2] = {
|
||||
{0x0000989c, 0x00000000 },
|
||||
{0x0000989c, 0x00000000 },
|
||||
@ -1956,7 +1956,6 @@ static u32 ar5416Addac_9160[][2] = {
|
||||
{0x000098cc, 0x00000000 },
|
||||
};
|
||||
|
||||
|
||||
static u32 ar5416Addac_91601_1[][2] = {
|
||||
{0x0000989c, 0x00000000 },
|
||||
{0x0000989c, 0x00000000 },
|
||||
@ -1992,8 +1991,7 @@ static u32 ar5416Addac_91601_1[][2] = {
|
||||
{0x000098cc, 0x00000000 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* XXX 9280 1 */
|
||||
static const u32 ar9280Modes_9280[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
@ -2543,9 +2541,7 @@ static const u32 ar9280Common_9280[][2] = {
|
||||
{ 0x00007898, 0x2a850160 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* XXX 9280 2 */
|
||||
static const u32 ar9280Modes_9280_2[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
@ -2560,26 +2556,24 @@ static const u32 ar9280Modes_9280_2[][6] = {
|
||||
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
|
||||
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
|
||||
{ 0x00009840, 0x206a012e, 0x206a012e, 0x206a022e, 0x206a022e, 0x206a022e },
|
||||
{ 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
|
||||
{ 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
|
||||
{ 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
|
||||
{ 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
|
||||
{ 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
|
||||
{ 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e },
|
||||
{ 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
|
||||
{ 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
|
||||
{ 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
|
||||
{ 0x0000c864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
|
||||
{ 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
|
||||
{ 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
|
||||
{ 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
|
||||
{ 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 },
|
||||
{ 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
|
||||
{ 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 },
|
||||
{ 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
|
||||
{ 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
|
||||
{ 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
|
||||
{ 0x0000c9b8, 0x0000000f, 0x0000000f, 0x0000001c, 0x0000001c, 0x0000001c },
|
||||
{ 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
|
||||
{ 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
|
||||
{ 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
|
||||
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
|
||||
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
|
||||
{ 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
|
||||
@ -2587,164 +2581,13 @@ static const u32 ar9280Modes_9280_2[][6] = {
|
||||
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
|
||||
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
|
||||
{ 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
|
||||
{ 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
|
||||
{ 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
|
||||
{ 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
|
||||
{ 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
|
||||
{ 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
|
||||
{ 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
|
||||
{ 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
|
||||
{ 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
|
||||
{ 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
|
||||
{ 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
|
||||
{ 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
|
||||
{ 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
|
||||
{ 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
|
||||
{ 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
|
||||
{ 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
|
||||
{ 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
|
||||
{ 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
|
||||
{ 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
|
||||
{ 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
|
||||
{ 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
|
||||
{ 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
|
||||
{ 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
|
||||
{ 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
|
||||
{ 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
|
||||
{ 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
|
||||
{ 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
|
||||
{ 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
|
||||
{ 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
|
||||
{ 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
|
||||
{ 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
|
||||
{ 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
|
||||
{ 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
|
||||
{ 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
|
||||
{ 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
|
||||
{ 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
|
||||
{ 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
|
||||
{ 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
|
||||
{ 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
|
||||
{ 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
|
||||
{ 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
|
||||
{ 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
|
||||
{ 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
|
||||
{ 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
|
||||
{ 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
|
||||
{ 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
|
||||
{ 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
|
||||
{ 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
|
||||
{ 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
|
||||
{ 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
|
||||
{ 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
|
||||
{ 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
|
||||
{ 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
|
||||
{ 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
|
||||
{ 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
|
||||
{ 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
|
||||
{ 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
|
||||
{ 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
|
||||
{ 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
|
||||
{ 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
|
||||
{ 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
|
||||
{ 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
|
||||
{ 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
|
||||
{ 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
|
||||
{ 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
|
||||
{ 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
|
||||
{ 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
|
||||
{ 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
|
||||
{ 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
|
||||
{ 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
|
||||
{ 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
|
||||
{ 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
|
||||
{ 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
|
||||
{ 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
|
||||
{ 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
|
||||
{ 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
|
||||
{ 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
|
||||
{ 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
|
||||
{ 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
|
||||
{ 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
|
||||
{ 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
|
||||
{ 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
|
||||
{ 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
|
||||
{ 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
|
||||
{ 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
|
||||
{ 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
|
||||
{ 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
|
||||
{ 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
|
||||
{ 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
|
||||
{ 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
|
||||
{ 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
|
||||
{ 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
|
||||
{ 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
|
||||
{ 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
|
||||
{ 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
|
||||
{ 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
|
||||
{ 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
|
||||
{ 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
|
||||
{ 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
|
||||
{ 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 },
|
||||
{ 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
|
||||
{ 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
|
||||
{ 0x0000a21c, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a },
|
||||
{ 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
|
||||
{ 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
|
||||
{ 0x0000a250, 0x001ff000, 0x001ff000, 0x001da000, 0x001da000, 0x001da000 },
|
||||
{ 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
|
||||
{ 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
|
||||
{ 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
|
||||
{ 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
|
||||
{ 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
|
||||
{ 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
|
||||
{ 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
|
||||
{ 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
|
||||
{ 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
|
||||
{ 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
|
||||
{ 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
|
||||
{ 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
|
||||
{ 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
|
||||
{ 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
|
||||
{ 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
|
||||
{ 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
|
||||
{ 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
|
||||
{ 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
|
||||
{ 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
|
||||
{ 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
|
||||
{ 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
|
||||
{ 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
|
||||
{ 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
|
||||
{ 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
|
||||
@ -2884,7 +2727,7 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x00008134, 0x00000000 },
|
||||
{ 0x00008138, 0x00000000 },
|
||||
{ 0x0000813c, 0x00000000 },
|
||||
{ 0x00008144, 0x00000000 },
|
||||
{ 0x00008144, 0xffffffff },
|
||||
{ 0x00008168, 0x00000000 },
|
||||
{ 0x0000816c, 0x00000000 },
|
||||
{ 0x00008170, 0x32143320 },
|
||||
@ -2923,6 +2766,7 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
@ -2939,7 +2783,7 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x0000832c, 0x00000007 },
|
||||
{ 0x00008330, 0x00000302 },
|
||||
{ 0x00008334, 0x00000e00 },
|
||||
{ 0x00008338, 0x00000000 },
|
||||
{ 0x00008338, 0x00ff0000 },
|
||||
{ 0x0000833c, 0x00000000 },
|
||||
{ 0x00008340, 0x000107ff },
|
||||
{ 0x00008344, 0x00581043 },
|
||||
@ -2973,7 +2817,7 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x00009958, 0x2108ecff },
|
||||
{ 0x00009940, 0x14750604 },
|
||||
{ 0x0000c95c, 0x004b6a8e },
|
||||
{ 0x0000c968, 0x000003ce },
|
||||
{ 0x00009968, 0x000003ce },
|
||||
{ 0x00009970, 0x190fb515 },
|
||||
{ 0x00009974, 0x00000000 },
|
||||
{ 0x00009978, 0x00000001 },
|
||||
@ -2999,13 +2843,14 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x000099ec, 0x0cc80caa },
|
||||
{ 0x000099f0, 0x00000000 },
|
||||
{ 0x000099fc, 0x00001042 },
|
||||
{ 0x0000a208, 0x803e4788 },
|
||||
{ 0x0000a210, 0x4080a333 },
|
||||
{ 0x0000a214, 0x40206c10 },
|
||||
{ 0x0000a218, 0x009c4060 },
|
||||
{ 0x0000a220, 0x01834061 },
|
||||
{ 0x0000a224, 0x00000400 },
|
||||
{ 0x0000a228, 0x000003b5 },
|
||||
{ 0x0000a22c, 0x233f71c0 },
|
||||
{ 0x0000a22c, 0x233f7180 },
|
||||
{ 0x0000a234, 0x20202020 },
|
||||
{ 0x0000a238, 0x20202020 },
|
||||
{ 0x0000a23c, 0x13c88000 },
|
||||
@ -3022,7 +2867,6 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x0000b26c, 0x0ebae9c6 },
|
||||
{ 0x0000d270, 0x00820820 },
|
||||
{ 0x0000a278, 0x1ce739ce },
|
||||
{ 0x0000a27c, 0x050701ce },
|
||||
{ 0x0000d35c, 0x07ffffef },
|
||||
{ 0x0000d360, 0x0fffffe7 },
|
||||
{ 0x0000d364, 0x17ffffe5 },
|
||||
@ -3064,7 +2908,6 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x00007808, 0x04924914 },
|
||||
{ 0x0000780c, 0x21084210 },
|
||||
{ 0x00007810, 0x6d801300 },
|
||||
{ 0x00007814, 0x0019beff },
|
||||
{ 0x00007818, 0x07e41000 },
|
||||
{ 0x0000781c, 0x00392000 },
|
||||
{ 0x00007820, 0x92592480 },
|
||||
@ -3073,7 +2916,6 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x0000782c, 0x04924914 },
|
||||
{ 0x00007830, 0x21084210 },
|
||||
{ 0x00007834, 0x6d801300 },
|
||||
{ 0x00007838, 0x0019beff },
|
||||
{ 0x0000783c, 0x07e40000 },
|
||||
{ 0x00007840, 0x00392000 },
|
||||
{ 0x00007844, 0x92592480 },
|
||||
@ -3110,12 +2952,465 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
|
||||
{ 0x00009828, 0x0b020001, 0x0b020001 },
|
||||
{ 0x00009834, 0x00000f0f, 0x00000f0f },
|
||||
{ 0x00009844, 0x03721821, 0x03721821 },
|
||||
{ 0x00009914, 0x00000898, 0x00000898 },
|
||||
{ 0x00009914, 0x00000898, 0x00001130 },
|
||||
{ 0x00009918, 0x0000000b, 0x00000016 },
|
||||
{ 0x00009944, 0xdfbc1210, 0xdfbc1210 },
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
|
||||
{ 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
|
||||
{ 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
|
||||
{ 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
|
||||
{ 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
|
||||
{ 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
|
||||
{ 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
|
||||
{ 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
|
||||
{ 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
|
||||
{ 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
|
||||
{ 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
|
||||
{ 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
|
||||
{ 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
|
||||
{ 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
|
||||
{ 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
|
||||
{ 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
|
||||
{ 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
|
||||
{ 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
|
||||
{ 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
|
||||
{ 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
|
||||
{ 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
|
||||
{ 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
|
||||
{ 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
|
||||
{ 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
|
||||
{ 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
|
||||
{ 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
|
||||
{ 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
|
||||
{ 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
|
||||
{ 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
|
||||
{ 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
|
||||
{ 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
|
||||
{ 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
|
||||
{ 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
|
||||
{ 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
|
||||
{ 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
|
||||
{ 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
|
||||
{ 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
|
||||
{ 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
|
||||
{ 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
|
||||
{ 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
|
||||
{ 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
|
||||
{ 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
|
||||
{ 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
|
||||
{ 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
|
||||
{ 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
|
||||
{ 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
|
||||
{ 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
|
||||
{ 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
|
||||
{ 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
|
||||
{ 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 },
|
||||
{ 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 },
|
||||
{ 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 },
|
||||
{ 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 },
|
||||
{ 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 },
|
||||
{ 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d },
|
||||
{ 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 },
|
||||
{ 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 },
|
||||
{ 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 },
|
||||
{ 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 },
|
||||
{ 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a },
|
||||
{ 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e },
|
||||
{ 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 },
|
||||
{ 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 },
|
||||
{ 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 },
|
||||
{ 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 },
|
||||
{ 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b },
|
||||
{ 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f },
|
||||
{ 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 },
|
||||
{ 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 },
|
||||
{ 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 },
|
||||
{ 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 },
|
||||
{ 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b },
|
||||
{ 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f },
|
||||
{ 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 },
|
||||
{ 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 },
|
||||
{ 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 },
|
||||
{ 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 },
|
||||
{ 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b },
|
||||
{ 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f },
|
||||
{ 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 },
|
||||
{ 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 },
|
||||
{ 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
|
||||
{ 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
|
||||
{ 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
|
||||
{ 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
|
||||
{ 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
|
||||
{ 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
|
||||
{ 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
|
||||
{ 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
|
||||
{ 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
|
||||
{ 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
|
||||
{ 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
|
||||
{ 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
|
||||
{ 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
|
||||
{ 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
|
||||
{ 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
|
||||
{ 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
|
||||
{ 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
|
||||
{ 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
|
||||
{ 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
|
||||
{ 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
|
||||
{ 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
|
||||
{ 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
|
||||
{ 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
|
||||
{ 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
|
||||
{ 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
|
||||
{ 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
|
||||
{ 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
|
||||
{ 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
|
||||
{ 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
|
||||
{ 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
|
||||
{ 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
|
||||
{ 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
|
||||
{ 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
|
||||
{ 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
|
||||
{ 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
|
||||
{ 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
|
||||
{ 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
|
||||
{ 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
|
||||
{ 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
|
||||
{ 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
|
||||
{ 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
|
||||
{ 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
|
||||
{ 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
|
||||
{ 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
|
||||
{ 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
|
||||
{ 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
|
||||
{ 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
|
||||
{ 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
|
||||
{ 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
|
||||
{ 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
|
||||
{ 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
|
||||
{ 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
|
||||
{ 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
|
||||
{ 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
|
||||
{ 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
|
||||
{ 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
|
||||
{ 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
|
||||
{ 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
|
||||
{ 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
|
||||
{ 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
|
||||
{ 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
|
||||
{ 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
|
||||
{ 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
|
||||
{ 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
|
||||
{ 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
|
||||
{ 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
|
||||
{ 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
|
||||
{ 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
|
||||
{ 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
|
||||
{ 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
|
||||
{ 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
|
||||
{ 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
|
||||
{ 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
|
||||
{ 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
|
||||
{ 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
|
||||
{ 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
|
||||
{ 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
|
||||
{ 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
|
||||
{ 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
|
||||
{ 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
|
||||
{ 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
|
||||
{ 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
|
||||
{ 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
|
||||
{ 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
|
||||
{ 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
|
||||
{ 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
|
||||
{ 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
|
||||
{ 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
|
||||
{ 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
|
||||
{ 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
|
||||
{ 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
|
||||
{ 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
|
||||
{ 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
|
||||
{ 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
|
||||
{ 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
|
||||
{ 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
|
||||
{ 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
|
||||
{ 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
|
||||
{ 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
|
||||
{ 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
|
||||
{ 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
|
||||
{ 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
|
||||
{ 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
|
||||
{ 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
|
||||
{ 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
|
||||
{ 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
|
||||
{ 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
|
||||
{ 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
|
||||
{ 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
|
||||
{ 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
|
||||
{ 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
|
||||
{ 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
|
||||
{ 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
|
||||
{ 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
|
||||
{ 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
|
||||
{ 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
|
||||
{ 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
|
||||
{ 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
|
||||
{ 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
|
||||
{ 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
|
||||
{ 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
|
||||
{ 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
|
||||
{ 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
|
||||
{ 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
|
||||
{ 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
|
||||
{ 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
|
||||
{ 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
|
||||
{ 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
|
||||
{ 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
|
||||
{ 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
|
||||
{ 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
|
||||
{ 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
|
||||
{ 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
|
||||
{ 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
|
||||
{ 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
|
||||
{ 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
|
||||
{ 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
|
||||
{ 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
|
||||
{ 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
|
||||
{ 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
|
||||
{ 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
|
||||
{ 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
|
||||
{ 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
|
||||
{ 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
|
||||
{ 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
|
||||
{ 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
|
||||
{ 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
|
||||
{ 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
|
||||
{ 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
|
||||
{ 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
|
||||
{ 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
|
||||
{ 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
|
||||
{ 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
|
||||
{ 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
|
||||
{ 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
|
||||
{ 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
|
||||
{ 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
|
||||
{ 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
|
||||
{ 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
|
||||
{ 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
|
||||
{ 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
|
||||
{ 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
|
||||
{ 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
|
||||
{ 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 },
|
||||
{ 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 },
|
||||
{ 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 },
|
||||
{ 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 },
|
||||
{ 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 },
|
||||
{ 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c },
|
||||
{ 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 },
|
||||
{ 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 },
|
||||
{ 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 },
|
||||
{ 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 },
|
||||
{ 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 },
|
||||
{ 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d },
|
||||
{ 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 },
|
||||
{ 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 },
|
||||
{ 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 },
|
||||
{ 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 },
|
||||
{ 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a },
|
||||
{ 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e },
|
||||
{ 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 },
|
||||
{ 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 },
|
||||
{ 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 },
|
||||
{ 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 },
|
||||
{ 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b },
|
||||
{ 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f },
|
||||
{ 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 },
|
||||
{ 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 },
|
||||
{ 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 },
|
||||
{ 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 },
|
||||
{ 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b },
|
||||
{ 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f },
|
||||
{ 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 },
|
||||
{ 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 },
|
||||
{ 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
|
||||
{ 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
|
||||
{ 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
|
||||
{ 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
|
||||
{ 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 },
|
||||
{ 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 },
|
||||
{ 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 },
|
||||
{ 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a },
|
||||
{ 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 },
|
||||
{ 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
|
||||
{ 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411, 0x00022411 },
|
||||
{ 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413, 0x00025413 },
|
||||
{ 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811, 0x00029811 },
|
||||
{ 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813, 0x0002c813 },
|
||||
{ 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
|
||||
{ 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50, 0x00035a50 },
|
||||
{ 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
|
||||
{ 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
|
||||
{ 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92, 0x00042e92 },
|
||||
{ 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
|
||||
{ 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
|
||||
{ 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
|
||||
{ 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5, 0x00053fd5 },
|
||||
{ 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
|
||||
{ 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
|
||||
{ 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
|
||||
{ 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
|
||||
{ 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
|
||||
{ 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
|
||||
{ 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
|
||||
{ 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
|
||||
{ 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
|
||||
{ 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
|
||||
{ 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
|
||||
{ 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
|
||||
{ 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
|
||||
{ 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
|
||||
{ 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
|
||||
{ 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
|
||||
{ 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
|
||||
{ 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
|
||||
{ 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
|
||||
{ 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
|
||||
{ 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
|
||||
{ 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
|
||||
{ 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
|
||||
{ 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
|
||||
{ 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
|
||||
{ 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
|
||||
};
|
||||
|
||||
static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
|
||||
{0x00004040, 0x9248fd00 },
|
||||
@ -3123,23 +3418,21 @@ static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
|
||||
{0x00004040, 0xa8000019 },
|
||||
{0x00004040, 0x13160820 },
|
||||
{0x00004040, 0xe5980560 },
|
||||
{0x00004040, 0x401dcffc },
|
||||
{0x00004040, 0x1aaabe40 },
|
||||
{0x00004040, 0xc01dcffc },
|
||||
{0x00004040, 0x1aaabe41 },
|
||||
{0x00004040, 0xbe105554 },
|
||||
{0x00004040, 0x00043007 },
|
||||
{0x00004044, 0x00000000 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
|
||||
{0x00004040, 0x9248fd00 },
|
||||
{0x00004040, 0x24924924 },
|
||||
{0x00004040, 0xa8000019 },
|
||||
{0x00004040, 0x13160820 },
|
||||
{0x00004040, 0xe5980560 },
|
||||
{0x00004040, 0x401dcffd },
|
||||
{0x00004040, 0x1aaabe40 },
|
||||
{0x00004040, 0xc01dcffd },
|
||||
{0x00004040, 0x1aaabe41 },
|
||||
{0x00004040, 0xbe105554 },
|
||||
{0x00004040, 0x00043007 },
|
||||
{0x00004044, 0x00000000 },
|
||||
|
@ -293,8 +293,10 @@ int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
|
||||
ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (ads->ds_txstatus1 & AR_Filtered)
|
||||
ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
|
||||
if (ads->ds_txstatus1 & AR_FIFOUnderrun)
|
||||
if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
|
||||
ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->ds_txstatus9 & AR_TxOpExceeded)
|
||||
ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
|
||||
if (ads->ds_txstatus1 & AR_TxTimerExpired)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -20,83 +20,24 @@
|
||||
#define RC_H
|
||||
|
||||
#include "ath9k.h"
|
||||
/*
|
||||
* Interface definitions for transmit rate control modules for the
|
||||
* Atheros driver.
|
||||
*
|
||||
* A rate control module is responsible for choosing the transmit rate
|
||||
* for each data frame. Management+control frames are always sent at
|
||||
* a fixed rate.
|
||||
*
|
||||
* Only one module may be present at a time; the driver references
|
||||
* rate control interfaces by symbol name. If multiple modules are
|
||||
* to be supported we'll need to switch to a registration-based scheme
|
||||
* as is currently done, for example, for authentication modules.
|
||||
*
|
||||
* An instance of the rate control module is attached to each device
|
||||
* at attach time and detached when the device is destroyed. The module
|
||||
* may associate data with each device and each node (station). Both
|
||||
* sets of storage are opaque except for the size of the per-node storage
|
||||
* which must be provided when the module is attached.
|
||||
*
|
||||
* The rate control module is notified for each state transition and
|
||||
* station association/reassociation. Otherwise it is queried for a
|
||||
* rate for each outgoing frame and provided status from each transmitted
|
||||
* frame. Any ancillary processing is the responsibility of the module
|
||||
* (e.g. if periodic processing is required then the module should setup
|
||||
* it's own timer).
|
||||
*
|
||||
* In addition to the transmit rate for each frame the module must also
|
||||
* indicate the number of attempts to make at the specified rate. If this
|
||||
* number is != ATH_TXMAXTRY then an additional callback is made to setup
|
||||
* additional transmit state. The rate control code is assumed to write
|
||||
* this additional data directly to the transmit descriptor.
|
||||
*/
|
||||
|
||||
struct ath_softc;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define ATH_RATE_MAX 30
|
||||
#define RATE_TABLE_SIZE 64
|
||||
#define MAX_TX_RATE_PHY 48
|
||||
|
||||
#define ATH_RATE_MAX 30
|
||||
/* VALID_ALL - valid for 20/40/Legacy,
|
||||
* VALID - Legacy only,
|
||||
* VALID_20 - HT 20 only,
|
||||
* VALID_40 - HT 40 only */
|
||||
|
||||
enum ieee80211_fixed_rate_mode {
|
||||
IEEE80211_FIXED_RATE_NONE = 0,
|
||||
IEEE80211_FIXED_RATE_MCS = 1 /* HT rates */
|
||||
};
|
||||
|
||||
/*
|
||||
* Use the hal os glue code to get ms time
|
||||
*/
|
||||
#define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8)))
|
||||
|
||||
#define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS
|
||||
#define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS
|
||||
#define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI
|
||||
#define WLAN_PHY_HT_40_SS WLAN_RC_PHY_HT_40_SS
|
||||
#define WLAN_PHY_HT_40_SS_HGI WLAN_RC_PHY_HT_40_SS_HGI
|
||||
#define WLAN_PHY_HT_40_DS WLAN_RC_PHY_HT_40_DS
|
||||
#define WLAN_PHY_HT_40_DS_HGI WLAN_RC_PHY_HT_40_DS_HGI
|
||||
|
||||
#define WLAN_PHY_OFDM PHY_OFDM
|
||||
#define WLAN_PHY_CCK PHY_CCK
|
||||
|
||||
#define TRUE_20 0x2
|
||||
#define TRUE_40 0x4
|
||||
#define TRUE_2040 (TRUE_20|TRUE_40)
|
||||
#define TRUE_ALL (TRUE_2040|TRUE)
|
||||
|
||||
enum {
|
||||
WLAN_RC_PHY_HT_20_SS = 4,
|
||||
WLAN_RC_PHY_HT_20_DS,
|
||||
WLAN_RC_PHY_HT_40_SS,
|
||||
WLAN_RC_PHY_HT_40_DS,
|
||||
WLAN_RC_PHY_HT_20_SS_HGI,
|
||||
WLAN_RC_PHY_HT_20_DS_HGI,
|
||||
WLAN_RC_PHY_HT_40_SS_HGI,
|
||||
WLAN_RC_PHY_HT_40_DS_HGI,
|
||||
WLAN_RC_PHY_MAX
|
||||
};
|
||||
#define INVALID 0x0
|
||||
#define VALID 0x1
|
||||
#define VALID_20 0x2
|
||||
#define VALID_40 0x4
|
||||
#define VALID_2040 (VALID_20|VALID_40)
|
||||
#define VALID_ALL (VALID_2040|VALID)
|
||||
|
||||
#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
|
||||
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
|
||||
@ -113,26 +54,22 @@ enum {
|
||||
|
||||
#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
|
||||
|
||||
/* Returns the capflag mode */
|
||||
#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
|
||||
(capflag & WLAN_RC_40_FLAG) ? TRUE_40 : TRUE_20 : TRUE))
|
||||
(capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
|
||||
|
||||
/* Return TRUE if flag supports HT20 && client supports HT20 or
|
||||
* return TRUE if flag supports HT40 && client supports HT40.
|
||||
* This is used becos some rates overlap between HT20/HT40.
|
||||
*/
|
||||
|
||||
#define WLAN_RC_PHY_HT_VALID(flag, capflag) (((flag & TRUE_20) && !(capflag \
|
||||
& WLAN_RC_40_FLAG)) || ((flag & TRUE_40) && \
|
||||
(capflag & WLAN_RC_40_FLAG)))
|
||||
#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
|
||||
(((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
|
||||
((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
|
||||
|
||||
#define WLAN_RC_DS_FLAG (0x01)
|
||||
#define WLAN_RC_40_FLAG (0x02)
|
||||
#define WLAN_RC_SGI_FLAG (0x04)
|
||||
#define WLAN_RC_HT_FLAG (0x08)
|
||||
|
||||
#define RATE_TABLE_SIZE 64
|
||||
|
||||
/**
|
||||
* struct ath_rate_table - Rate Control table
|
||||
* @valid: valid for use in rate control
|
||||
@ -149,10 +86,11 @@ enum {
|
||||
* @max_4ms_framelen: maximum frame length(bytes) for tx duration
|
||||
* @probe_interval: interval for rate control to probe for other rates
|
||||
* @rssi_reduce_interval: interval for rate control to reduce rssi
|
||||
* @initial_ratemax: initial ratemax value used in ath_rc_sib_update()
|
||||
* @initial_ratemax: initial ratemax value
|
||||
*/
|
||||
struct ath_rate_table {
|
||||
int rate_cnt;
|
||||
u8 rateCodeToIndex[256];
|
||||
struct {
|
||||
int valid;
|
||||
int valid_single_stream;
|
||||
@ -170,42 +108,26 @@ struct ath_rate_table {
|
||||
u8 sgi_index;
|
||||
u8 ht_index;
|
||||
u32 max_4ms_framelen;
|
||||
u16 lpAckDuration;
|
||||
u16 spAckDuration;
|
||||
} info[RATE_TABLE_SIZE];
|
||||
u32 probe_interval;
|
||||
u32 rssi_reduce_interval;
|
||||
u8 initial_ratemax;
|
||||
};
|
||||
|
||||
#define ATH_RC_PROBE_ALLOWED 0x00000001
|
||||
#define ATH_RC_MINRATE_LASTRATE 0x00000002
|
||||
|
||||
struct ath_rc_series {
|
||||
u8 rix;
|
||||
u8 tries;
|
||||
u8 flags;
|
||||
u32 max_4ms_framelen;
|
||||
};
|
||||
|
||||
/* rcs_flags definition */
|
||||
#define ATH_RC_DS_FLAG 0x01
|
||||
#define ATH_RC_CW40_FLAG 0x02 /* CW 40 */
|
||||
#define ATH_RC_SGI_FLAG 0x04 /* Short Guard Interval */
|
||||
#define ATH_RC_HT_FLAG 0x08 /* HT */
|
||||
#define ATH_RC_RTSCTS_FLAG 0x10 /* RTS-CTS */
|
||||
|
||||
/*
|
||||
* State structures for new rate adaptation code
|
||||
*/
|
||||
#define MAX_TX_RATE_TBL 64
|
||||
#define MAX_TX_RATE_PHY 48
|
||||
|
||||
struct ath_tx_ratectrl_state {
|
||||
int8_t rssi_thres; /* required rssi for this rate (dB) */
|
||||
u8 per; /* recent estimate of packet error rate (%) */
|
||||
};
|
||||
|
||||
struct ath_rateset {
|
||||
u8 rs_nrates;
|
||||
u8 rs_rates[ATH_RATE_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_tx_ratectrl - TX Rate control Information
|
||||
* struct ath_rate_priv - Rate Control priv data
|
||||
* @state: RC state
|
||||
* @rssi_last: last ACK rssi
|
||||
* @rssi_last_lookup: last ACK rssi used for lookup
|
||||
@ -224,9 +146,13 @@ struct ath_tx_ratectrl_state {
|
||||
* @valid_phy_ratecnt: valid rate count
|
||||
* @rate_max_phy: phy index for the max rate
|
||||
* @probe_interval: interval for ratectrl to probe for other rates
|
||||
* @prev_data_rix: rate idx of last data frame
|
||||
* @ht_cap: HT capabilities
|
||||
* @single_stream: When TRUE, only single TX stream possible
|
||||
* @neg_rates: Negotatied rates
|
||||
* @neg_ht_rates: Negotiated HT rates
|
||||
*/
|
||||
struct ath_tx_ratectrl {
|
||||
struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL];
|
||||
struct ath_rate_priv {
|
||||
int8_t rssi_last;
|
||||
int8_t rssi_last_lookup;
|
||||
int8_t rssi_last_prev;
|
||||
@ -236,89 +162,40 @@ struct ath_tx_ratectrl {
|
||||
int32_t rssi_sum;
|
||||
u8 rate_table_size;
|
||||
u8 probe_rate;
|
||||
u8 hw_maxretry_pktcnt;
|
||||
u8 max_valid_rate;
|
||||
u8 valid_rate_index[RATE_TABLE_SIZE];
|
||||
u8 ht_cap;
|
||||
u8 single_stream;
|
||||
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
|
||||
u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
|
||||
u8 rc_phy_mode;
|
||||
u8 rate_max_phy;
|
||||
u32 rssi_time;
|
||||
u32 rssi_down_time;
|
||||
u32 probe_time;
|
||||
u8 hw_maxretry_pktcnt;
|
||||
u8 max_valid_rate;
|
||||
u8 valid_rate_index[MAX_TX_RATE_TBL];
|
||||
u32 per_down_time;
|
||||
|
||||
/* 11n state */
|
||||
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
|
||||
u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL];
|
||||
u8 rc_phy_mode;
|
||||
u8 rate_max_phy;
|
||||
u32 probe_interval;
|
||||
};
|
||||
|
||||
struct ath_rateset {
|
||||
u8 rs_nrates;
|
||||
u8 rs_rates[ATH_RATE_MAX];
|
||||
};
|
||||
|
||||
/* per-device state */
|
||||
struct ath_rate_softc {
|
||||
/* phy tables that contain rate control data */
|
||||
const void *hw_rate_table[ATH9K_MODE_MAX];
|
||||
|
||||
/* -1 or index of fixed rate */
|
||||
int fixedrix;
|
||||
};
|
||||
|
||||
/* per-node state */
|
||||
struct ath_rate_node {
|
||||
struct ath_tx_ratectrl tx_ratectrl;
|
||||
|
||||
/* rate idx of last data frame */
|
||||
u32 prev_data_rix;
|
||||
|
||||
/* ht capabilities */
|
||||
u8 ht_cap;
|
||||
|
||||
/* When TRUE, only single stream Tx possible */
|
||||
u8 single_stream;
|
||||
|
||||
/* Negotiated rates */
|
||||
u32 tx_triglevel_max;
|
||||
struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
|
||||
struct ath_rateset neg_rates;
|
||||
|
||||
/* Negotiated HT rates */
|
||||
struct ath_rateset neg_ht_rates;
|
||||
|
||||
struct ath_rate_softc *asc;
|
||||
struct ath_vap *avp;
|
||||
};
|
||||
|
||||
/* Driver data of ieee80211_tx_info */
|
||||
struct ath_tx_info_priv {
|
||||
struct ath_rc_series rcs[4];
|
||||
struct ath_tx_status tx;
|
||||
int n_frames;
|
||||
int n_bad_frames;
|
||||
u8 min_rate;
|
||||
bool update_rc;
|
||||
};
|
||||
|
||||
/*
|
||||
* Attach/detach a rate control module.
|
||||
*/
|
||||
struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah);
|
||||
void ath_rate_detach(struct ath_rate_softc *asc);
|
||||
#define ATH_TX_INFO_PRIV(tx_info) \
|
||||
((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
|
||||
|
||||
/*
|
||||
* Update/reset rate control state for 802.11 state transitions.
|
||||
* Important mostly as the analog to ath_rate_newassoc when operating
|
||||
* in station mode.
|
||||
*/
|
||||
void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv);
|
||||
void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp);
|
||||
|
||||
/*
|
||||
* Return rate index for given Dot11 Rate.
|
||||
*/
|
||||
u8 ath_rate_findrateix(struct ath_softc *sc,
|
||||
u8 dot11_rate);
|
||||
|
||||
/* Routines to register/unregister rate control algorithm */
|
||||
void ath_rate_attach(struct ath_softc *sc);
|
||||
u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
|
||||
int ath_rate_control_register(void);
|
||||
void ath_rate_control_unregister(void);
|
||||
|
||||
|
@ -14,10 +14,6 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implementation of receive path.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/*
|
||||
@ -27,10 +23,7 @@
|
||||
* MAC acknowledges BA status as long as it copies frames to host
|
||||
* buffer (or rx fifo). This can incorrectly acknowledge packets
|
||||
* to a sender if last desc is self-linked.
|
||||
*
|
||||
* NOTE: Caller should hold the rxbuf lock.
|
||||
*/
|
||||
|
||||
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
@ -40,19 +33,17 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||
ATH_RXBUF_RESET(bf);
|
||||
|
||||
ds = bf->bf_desc;
|
||||
ds->ds_link = 0; /* link to null */
|
||||
ds->ds_link = 0; /* link to null */
|
||||
ds->ds_data = bf->bf_buf_addr;
|
||||
|
||||
/* XXX For RADAR?
|
||||
* virtual addr of the beginning of the buffer. */
|
||||
/* virtual addr of the beginning of the buffer. */
|
||||
skb = bf->bf_mpdu;
|
||||
ASSERT(skb != NULL);
|
||||
ds->ds_vdata = skb->data;
|
||||
|
||||
/* setup rx descriptors */
|
||||
ath9k_hw_setuprxdesc(ah,
|
||||
ds,
|
||||
skb_tailroom(skb), /* buffer size */
|
||||
ath9k_hw_setuprxdesc(ah, ds,
|
||||
skb_tailroom(skb), /* buffer size */
|
||||
0);
|
||||
|
||||
if (sc->sc_rxlink == NULL)
|
||||
@ -64,8 +55,29 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||
ath9k_hw_rxena(ah);
|
||||
}
|
||||
|
||||
static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
|
||||
u32 len)
|
||||
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
|
||||
{
|
||||
/* XXX block beacon interrupts */
|
||||
ath9k_hw_setantenna(sc->sc_ah, antenna);
|
||||
sc->sc_defant = antenna;
|
||||
sc->sc_rxotherant = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extend 15-bit time stamp from rx descriptor to
|
||||
* a full 64-bit TSF using the current h/w TSF.
|
||||
*/
|
||||
static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
|
||||
{
|
||||
u64 tsf;
|
||||
|
||||
tsf = ath9k_hw_gettsf64(sc->sc_ah);
|
||||
if ((tsf & 0x7fff) < rstamp)
|
||||
tsf -= 0x8000;
|
||||
return (tsf & ~0x7fff) | rstamp;
|
||||
}
|
||||
|
||||
static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u32 off;
|
||||
@ -91,59 +103,133 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static void ath_rx_requeue(struct ath_softc *sc, struct sk_buff *skb)
|
||||
static int ath_rate2idx(struct ath_softc *sc, int rate)
|
||||
{
|
||||
struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf;
|
||||
int i = 0, cur_band, n_rates;
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
|
||||
ASSERT(bf != NULL);
|
||||
cur_band = hw->conf.channel->band;
|
||||
n_rates = sc->sbands[cur_band].n_bitrates;
|
||||
|
||||
spin_lock_bh(&sc->sc_rxbuflock);
|
||||
if (bf->bf_status & ATH_BUFSTATUS_STALE) {
|
||||
/*
|
||||
* This buffer is still held for hw acess.
|
||||
* Mark it as free to be re-queued it later.
|
||||
*/
|
||||
bf->bf_status |= ATH_BUFSTATUS_FREE;
|
||||
} else {
|
||||
/* XXX: we probably never enter here, remove after
|
||||
* verification */
|
||||
list_add_tail(&bf->list, &sc->sc_rxbuf);
|
||||
ath_rx_buf_link(sc, bf);
|
||||
for (i = 0; i < n_rates; i++) {
|
||||
if (sc->sbands[cur_band].bitrates[i].bitrate == rate)
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
|
||||
/*
|
||||
* NB:mac80211 validates rx rate index against the supported legacy rate
|
||||
* index only (should be done against ht rates also), return the highest
|
||||
* legacy rate index for rx rate which does not match any one of the
|
||||
* supported basic and extended rates to make mac80211 happy.
|
||||
* The following hack will be cleaned up once the issue with
|
||||
* the rx rate index validation in mac80211 is fixed.
|
||||
*/
|
||||
if (i == n_rates)
|
||||
return n_rates - 1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* The skb indicated to upper stack won't be returned to us.
|
||||
* So we have to allocate a new one and queue it by ourselves.
|
||||
* For Decrypt or Demic errors, we only mark packet status here and always push
|
||||
* up the frame up to let mac80211 handle the actual error case, be it no
|
||||
* decryption key or real decryption error. This let us keep statistics there.
|
||||
*/
|
||||
static int ath_rx_indicate(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
struct ath_recv_status *status,
|
||||
u16 keyix)
|
||||
static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
|
||||
struct ieee80211_rx_status *rx_status, bool *decrypt_error,
|
||||
struct ath_softc *sc)
|
||||
{
|
||||
struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf;
|
||||
struct sk_buff *nskb;
|
||||
int type;
|
||||
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
|
||||
struct ieee80211_hdr *hdr;
|
||||
int ratekbps, rix;
|
||||
u8 ratecode;
|
||||
__le16 fc;
|
||||
|
||||
/* indicate frame to the stack, which will free the old skb. */
|
||||
type = _ath_rx_indicate(sc, skb, status, keyix);
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
|
||||
|
||||
/* allocate a new skb and queue it to for H/W processing */
|
||||
nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
|
||||
if (nskb != NULL) {
|
||||
bf->bf_mpdu = nskb;
|
||||
bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data,
|
||||
skb_end_pointer(nskb) - nskb->head,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->bf_dmacontext = bf->bf_buf_addr;
|
||||
ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf;
|
||||
if (ds->ds_rxstat.rs_more) {
|
||||
/*
|
||||
* Frame spans multiple descriptors; this cannot happen yet
|
||||
* as we don't support jumbograms. If not in monitor mode,
|
||||
* discard the frame. Enable this if you want to see
|
||||
* error frames in Monitor mode.
|
||||
*/
|
||||
if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
|
||||
goto rx_next;
|
||||
} else if (ds->ds_rxstat.rs_status != 0) {
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
|
||||
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
|
||||
goto rx_next;
|
||||
|
||||
/* queue the new wbuf to H/W */
|
||||
ath_rx_requeue(sc, nskb);
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
*decrypt_error = true;
|
||||
} else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rx_status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
goto rx_next;
|
||||
} else {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
goto rx_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
ratecode = ds->ds_rxstat.rs_rate;
|
||||
rix = rate_table->rateCodeToIndex[ratecode];
|
||||
ratekbps = rate_table->info[rix].ratekbps;
|
||||
|
||||
/* HT rate */
|
||||
if (ratecode & 0x80) {
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
|
||||
ratekbps = (ratekbps * 27) / 13;
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
|
||||
ratekbps = (ratekbps * 10) / 9;
|
||||
}
|
||||
|
||||
rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
|
||||
rx_status->band = sc->hw->conf.channel->band;
|
||||
rx_status->freq = sc->hw->conf.channel->center_freq;
|
||||
rx_status->noise = sc->sc_ani.sc_noise_floor;
|
||||
rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
|
||||
rx_status->rate_idx = ath_rate2idx(sc, (ratekbps / 100));
|
||||
rx_status->antenna = ds->ds_rxstat.rs_antenna;
|
||||
|
||||
/* at 45 you will be able to use MCS 15 reliably. A more elaborate
|
||||
* scheme can be used here but it requires tables of SNR/throughput for
|
||||
* each possible mode used. */
|
||||
rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
|
||||
|
||||
/* rssi can be more than 45 though, anything above that
|
||||
* should be considered at 100% */
|
||||
if (rx_status->qual > 100)
|
||||
rx_status->qual = 100;
|
||||
|
||||
rx_status->flag |= RX_FLAG_TSFT;
|
||||
|
||||
return 1;
|
||||
rx_next:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath_opmode_init(struct ath_softc *sc)
|
||||
@ -185,12 +271,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_lock_init(&sc->sc_rxbuflock);
|
||||
|
||||
/*
|
||||
* Cisco's VPN software requires that drivers be able to
|
||||
* receive encapsulated frames that are larger than the MTU.
|
||||
* Since we can't be sure how large a frame we'll get, setup
|
||||
* to handle the larges on possible.
|
||||
*/
|
||||
sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN,
|
||||
min(sc->sc_cachelsz,
|
||||
(u16)64));
|
||||
@ -209,8 +289,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Pre-allocate a wbuf for each rx buffer */
|
||||
|
||||
list_for_each_entry(bf, &sc->sc_rxbuf, list) {
|
||||
skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
|
||||
if (skb == NULL) {
|
||||
@ -223,7 +301,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->bf_dmacontext = bf->bf_buf_addr;
|
||||
ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf;
|
||||
}
|
||||
sc->sc_rxlink = NULL;
|
||||
|
||||
@ -235,8 +312,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Reclaim all rx queue resources */
|
||||
|
||||
void ath_rx_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
@ -248,8 +323,6 @@ void ath_rx_cleanup(struct ath_softc *sc)
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* cleanup rx descriptors */
|
||||
|
||||
if (sc->sc_rxdma.dd_desc_len != 0)
|
||||
ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
|
||||
}
|
||||
@ -297,20 +370,19 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
|
||||
}
|
||||
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_STA ||
|
||||
sc->sc_ah->ah_opmode == ATH9K_M_IBSS)
|
||||
sc->sc_ah->ah_opmode == ATH9K_M_IBSS)
|
||||
rfilt |= ATH9K_RX_FILTER_BEACON;
|
||||
|
||||
/* If in HOSTAP mode, want to enable reception of PSPOLL frames
|
||||
& beacon frames */
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
|
||||
rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
|
||||
|
||||
return rfilt;
|
||||
|
||||
#undef RX_FILTER_PRESERVE
|
||||
}
|
||||
|
||||
/* Enable the receive h/w following a reset. */
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
@ -322,21 +394,6 @@ int ath_startrecv(struct ath_softc *sc)
|
||||
|
||||
sc->sc_rxlink = NULL;
|
||||
list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) {
|
||||
if (bf->bf_status & ATH_BUFSTATUS_STALE) {
|
||||
/* restarting h/w, no need for holding descriptors */
|
||||
bf->bf_status &= ~ATH_BUFSTATUS_STALE;
|
||||
/*
|
||||
* Upper layer may not be done with the frame yet so
|
||||
* we can't just re-queue it to hardware. Remove it
|
||||
* from h/w queue. It'll be re-queued when upper layer
|
||||
* returns the frame and ath_rx_requeue_mpdu is called.
|
||||
*/
|
||||
if (!(bf->bf_status & ATH_BUFSTATUS_FREE)) {
|
||||
list_del(&bf->list);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* chain descriptors */
|
||||
ath_rx_buf_link(sc, bf);
|
||||
}
|
||||
|
||||
@ -346,120 +403,69 @@ int ath_startrecv(struct ath_softc *sc)
|
||||
|
||||
bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
|
||||
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
|
||||
ath9k_hw_rxena(ah); /* enable recv descriptors */
|
||||
ath9k_hw_rxena(ah);
|
||||
|
||||
start_recv:
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
ath_opmode_init(sc); /* set filters, etc. */
|
||||
ath9k_hw_startpcureceive(ah); /* re-enable PCU/DMA engine */
|
||||
ath_opmode_init(sc);
|
||||
ath9k_hw_startpcureceive(ah);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Disable the receive h/w in preparation for a reset. */
|
||||
|
||||
bool ath_stoprecv(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
u64 tsf;
|
||||
bool stopped;
|
||||
|
||||
ath9k_hw_stoppcurecv(ah); /* disable PCU */
|
||||
ath9k_hw_setrxfilter(ah, 0); /* clear recv filter */
|
||||
stopped = ath9k_hw_stopdmarecv(ah); /* disable DMA engine */
|
||||
mdelay(3); /* 3ms is long enough for 1 frame */
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
sc->sc_rxlink = NULL; /* just in case */
|
||||
ath9k_hw_stoppcurecv(ah);
|
||||
ath9k_hw_setrxfilter(ah, 0);
|
||||
stopped = ath9k_hw_stopdmarecv(ah);
|
||||
mdelay(3); /* 3ms is long enough for 1 frame */
|
||||
sc->sc_rxlink = NULL;
|
||||
|
||||
return stopped;
|
||||
}
|
||||
|
||||
/* Flush receive queue */
|
||||
|
||||
void ath_flushrecv(struct ath_softc *sc)
|
||||
{
|
||||
/*
|
||||
* ath_rx_tasklet may be used to handle rx interrupt and flush receive
|
||||
* queue at the same time. Use a lock to serialize the access of rx
|
||||
* queue.
|
||||
* ath_rx_tasklet cannot hold the spinlock while indicating packets.
|
||||
* Instead, do not claim the spinlock but check for a flush in
|
||||
* progress (see references to sc_rxflush)
|
||||
*/
|
||||
spin_lock_bh(&sc->sc_rxflushlock);
|
||||
sc->sc_flags |= SC_OP_RXFLUSH;
|
||||
|
||||
ath_rx_tasklet(sc, 1);
|
||||
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_unlock_bh(&sc->sc_rxflushlock);
|
||||
}
|
||||
|
||||
/* Process receive queue, as well as LED, etc. */
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
{
|
||||
#define PA2DESC(_sc, _pa) \
|
||||
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
|
||||
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
|
||||
|
||||
struct ath_buf *bf, *bf_held = NULL;
|
||||
struct ath_buf *bf;
|
||||
struct ath_desc *ds;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct ath_recv_status rx_status;
|
||||
struct sk_buff *skb = NULL, *requeue_skb;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
int type, rx_processed = 0;
|
||||
u32 phyerr;
|
||||
u8 chainreset = 0;
|
||||
int retval;
|
||||
__le16 fc;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padsize, retval;
|
||||
bool decrypt_error = false;
|
||||
u8 keyix;
|
||||
|
||||
spin_lock_bh(&sc->sc_rxbuflock);
|
||||
|
||||
do {
|
||||
/* If handling rx interrupt and flush is in progress => exit */
|
||||
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
|
||||
break;
|
||||
|
||||
spin_lock_bh(&sc->sc_rxbuflock);
|
||||
if (list_empty(&sc->sc_rxbuf)) {
|
||||
sc->sc_rxlink = NULL;
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
break;
|
||||
}
|
||||
|
||||
bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
|
||||
|
||||
/*
|
||||
* There is a race condition that BH gets scheduled after sw
|
||||
* writes RxE and before hw re-load the last descriptor to get
|
||||
* the newly chained one. Software must keep the last DONE
|
||||
* descriptor as a holding descriptor - software does so by
|
||||
* marking it with the STALE flag.
|
||||
*/
|
||||
if (bf->bf_status & ATH_BUFSTATUS_STALE) {
|
||||
bf_held = bf;
|
||||
if (list_is_last(&bf_held->list, &sc->sc_rxbuf)) {
|
||||
/*
|
||||
* The holding descriptor is the last
|
||||
* descriptor in queue. It's safe to
|
||||
* remove the last holding descriptor
|
||||
* in BH context.
|
||||
*/
|
||||
list_del(&bf_held->list);
|
||||
bf_held->bf_status &= ~ATH_BUFSTATUS_STALE;
|
||||
sc->sc_rxlink = NULL;
|
||||
|
||||
if (bf_held->bf_status & ATH_BUFSTATUS_FREE) {
|
||||
list_add_tail(&bf_held->list,
|
||||
&sc->sc_rxbuf);
|
||||
ath_rx_buf_link(sc, bf_held);
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
break;
|
||||
}
|
||||
bf = list_entry(bf->list.next, struct ath_buf, list);
|
||||
}
|
||||
|
||||
ds = bf->bf_desc;
|
||||
++rx_processed;
|
||||
|
||||
/*
|
||||
* Must provide the virtual address of the current
|
||||
@ -472,8 +478,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
* on. All this is necessary because of our use of
|
||||
* a self-linked list to avoid rx overruns.
|
||||
*/
|
||||
retval = ath9k_hw_rxprocdesc(ah,
|
||||
ds,
|
||||
retval = ath9k_hw_rxprocdesc(ah, ds,
|
||||
bf->bf_daddr,
|
||||
PA2DESC(sc, ds->ds_link),
|
||||
0);
|
||||
@ -482,7 +487,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
struct ath_desc *tds;
|
||||
|
||||
if (list_is_last(&bf->list, &sc->sc_rxbuf)) {
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
sc->sc_rxlink = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -500,215 +505,87 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
*/
|
||||
|
||||
tds = tbf->bf_desc;
|
||||
retval = ath9k_hw_rxprocdesc(ah,
|
||||
tds, tbf->bf_daddr,
|
||||
PA2DESC(sc, tds->ds_link), 0);
|
||||
retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
|
||||
PA2DESC(sc, tds->ds_link), 0);
|
||||
if (retval == -EINPROGRESS) {
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: we do not support frames spanning
|
||||
* multiple descriptors */
|
||||
bf->bf_status |= ATH_BUFSTATUS_DONE;
|
||||
|
||||
skb = bf->bf_mpdu;
|
||||
if (skb == NULL) { /* XXX ??? can this happen */
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
if (!skb)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we know it's a completed frame, we can indicate the
|
||||
* frame. Remove the previous holding descriptor and leave
|
||||
* this one in the queue as the new holding descriptor.
|
||||
* If we're asked to flush receive queue, directly
|
||||
* chain it back at the queue without processing it.
|
||||
*/
|
||||
if (bf_held) {
|
||||
list_del(&bf_held->list);
|
||||
bf_held->bf_status &= ~ATH_BUFSTATUS_STALE;
|
||||
if (bf_held->bf_status & ATH_BUFSTATUS_FREE) {
|
||||
list_add_tail(&bf_held->list, &sc->sc_rxbuf);
|
||||
/* try to requeue this descriptor */
|
||||
ath_rx_buf_link(sc, bf_held);
|
||||
}
|
||||
}
|
||||
if (flush)
|
||||
goto requeue;
|
||||
|
||||
bf->bf_status |= ATH_BUFSTATUS_STALE;
|
||||
bf_held = bf;
|
||||
/*
|
||||
* Release the lock here in case ieee80211_input() return
|
||||
* the frame immediately by calling ath_rx_mpdu_requeue().
|
||||
*/
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
if (!ds->ds_rxstat.rs_datalen)
|
||||
goto requeue;
|
||||
|
||||
if (flush) {
|
||||
/*
|
||||
* If we're asked to flush receive queue, directly
|
||||
* chain it back at the queue without processing it.
|
||||
*/
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
memset(&rx_status, 0, sizeof(struct ath_recv_status));
|
||||
|
||||
if (ds->ds_rxstat.rs_more) {
|
||||
/*
|
||||
* Frame spans multiple descriptors; this
|
||||
* cannot happen yet as we don't support
|
||||
* jumbograms. If not in monitor mode,
|
||||
* discard the frame.
|
||||
*/
|
||||
#ifndef ERROR_FRAMES
|
||||
/*
|
||||
* Enable this if you want to see
|
||||
* error frames in Monitor mode.
|
||||
*/
|
||||
if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
|
||||
goto rx_next;
|
||||
#endif
|
||||
/* fall thru for monitor mode handling... */
|
||||
} else if (ds->ds_rxstat.rs_status != 0) {
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
|
||||
rx_status.flags |= ATH_RX_FCS_ERROR;
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
|
||||
phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
/*
|
||||
* Decrypt error. We only mark packet status
|
||||
* here and always push up the frame up to let
|
||||
* mac80211 handle the actual error case, be
|
||||
* it no decryption key or real decryption
|
||||
* error. This let us keep statistics there.
|
||||
*/
|
||||
rx_status.flags |= ATH_RX_DECRYPT_ERROR;
|
||||
} else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
|
||||
/*
|
||||
* Demic error. We only mark frame status here
|
||||
* and always push up the frame up to let
|
||||
* mac80211 handle the actual error case. This
|
||||
* let us keep statistics there. Hardware may
|
||||
* post a false-positive MIC error.
|
||||
*/
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
ds->ds_rxstat.rs_status &=
|
||||
~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rx_status.flags |= ATH_RX_MIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
goto rx_next;
|
||||
} else {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
goto rx_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The status portion of the descriptor could get corrupted.
|
||||
*/
|
||||
/* The status portion of the descriptor could get corrupted. */
|
||||
if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
|
||||
goto rx_next;
|
||||
/*
|
||||
* Sync and unmap the frame. At this point we're
|
||||
* committed to passing the sk_buff somewhere so
|
||||
* clear buf_skb; this means a new sk_buff must be
|
||||
* allocated when the rx descriptor is setup again
|
||||
* to receive another frame.
|
||||
*/
|
||||
skb_put(skb, ds->ds_rxstat.rs_datalen);
|
||||
skb->protocol = cpu_to_be16(ETH_P_CONTROL);
|
||||
rx_status.tsf = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
|
||||
rx_status.rateieee =
|
||||
sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate;
|
||||
rx_status.rateKbps =
|
||||
sc->sc_hwmap[ds->ds_rxstat.rs_rate].rateKbps;
|
||||
rx_status.ratecode = ds->ds_rxstat.rs_rate;
|
||||
goto requeue;
|
||||
|
||||
/* HT rate */
|
||||
if (rx_status.ratecode & 0x80) {
|
||||
/* TODO - add table to avoid division */
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) {
|
||||
rx_status.flags |= ATH_RX_40MHZ;
|
||||
rx_status.rateKbps =
|
||||
(rx_status.rateKbps * 27) / 13;
|
||||
}
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
|
||||
rx_status.rateKbps =
|
||||
(rx_status.rateKbps * 10) / 9;
|
||||
else
|
||||
rx_status.flags |= ATH_RX_SHORT_GI;
|
||||
}
|
||||
if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
|
||||
goto requeue;
|
||||
|
||||
/* sc_noise_floor is only available when the station
|
||||
attaches to an AP, so we use a default value
|
||||
if we are not yet attached. */
|
||||
rx_status.abs_rssi =
|
||||
ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor;
|
||||
/* Ensure we always have an skb to requeue once we are done
|
||||
* processing the current buffer's skb */
|
||||
requeue_skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
|
||||
|
||||
pci_dma_sync_single_for_cpu(sc->pdev,
|
||||
bf->bf_buf_addr,
|
||||
/* If there is no memory we ignore the current RX'd frame,
|
||||
* tell hardware it can give us a new frame using the old
|
||||
* skb and put it at the tail of the sc->sc_rxbuf list for
|
||||
* processing. */
|
||||
if (!requeue_skb)
|
||||
goto requeue;
|
||||
|
||||
/* Sync and unmap the frame */
|
||||
pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
|
||||
skb_tailroom(skb),
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pci_unmap_single(sc->pdev,
|
||||
bf->bf_buf_addr,
|
||||
pci_unmap_single(sc->pdev, bf->bf_buf_addr,
|
||||
sc->sc_rxbufsize,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
/* XXX: Ah! make me more readable, use a helper */
|
||||
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
if (ds->ds_rxstat.rs_moreaggr == 0) {
|
||||
rx_status.rssictl[0] =
|
||||
ds->ds_rxstat.rs_rssi_ctl0;
|
||||
rx_status.rssictl[1] =
|
||||
ds->ds_rxstat.rs_rssi_ctl1;
|
||||
rx_status.rssictl[2] =
|
||||
ds->ds_rxstat.rs_rssi_ctl2;
|
||||
rx_status.rssi = ds->ds_rxstat.rs_rssi;
|
||||
if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) {
|
||||
rx_status.rssiextn[0] =
|
||||
ds->ds_rxstat.rs_rssi_ext0;
|
||||
rx_status.rssiextn[1] =
|
||||
ds->ds_rxstat.rs_rssi_ext1;
|
||||
rx_status.rssiextn[2] =
|
||||
ds->ds_rxstat.rs_rssi_ext2;
|
||||
rx_status.flags |=
|
||||
ATH_RX_RSSI_EXTN_VALID;
|
||||
}
|
||||
rx_status.flags |= ATH_RX_RSSI_VALID |
|
||||
ATH_RX_CHAIN_RSSI_VALID;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Need to insert the "combined" rssi into the
|
||||
* status structure for upper layer processing
|
||||
*/
|
||||
rx_status.rssi = ds->ds_rxstat.rs_rssi;
|
||||
rx_status.flags |= ATH_RX_RSSI_VALID;
|
||||
skb_put(skb, ds->ds_rxstat.rs_datalen);
|
||||
skb->protocol = cpu_to_be16(ETH_P_CONTROL);
|
||||
|
||||
/* see if any padding is done by the hw and remove it */
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
|
||||
if (hdrlen & 3) {
|
||||
padsize = hdrlen % 4;
|
||||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
/* Pass frames up to the stack. */
|
||||
keyix = ds->ds_rxstat.rs_keyix;
|
||||
|
||||
type = ath_rx_indicate(sc, skb,
|
||||
&rx_status, ds->ds_rxstat.rs_keyix);
|
||||
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
|
||||
rx_status.flag |= RX_FLAG_DECRYPTED;
|
||||
} else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
|
||||
&& !decrypt_error && skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
if (test_bit(keyix, sc->sc_keymap))
|
||||
rx_status.flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
|
||||
/* Send the frame to mac80211 */
|
||||
__ieee80211_rx(sc->hw, skb, &rx_status);
|
||||
|
||||
/* We will now give hardware our shiny new allocated skb */
|
||||
bf->bf_mpdu = requeue_skb;
|
||||
bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data,
|
||||
sc->sc_rxbufsize,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->bf_dmacontext = bf->bf_buf_addr;
|
||||
|
||||
/*
|
||||
* change the default rx antenna if rx diversity chooses the
|
||||
@ -716,37 +593,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
*/
|
||||
if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
|
||||
if (++sc->sc_rxotherant >= 3)
|
||||
ath_setdefantenna(sc,
|
||||
ds->ds_rxstat.rs_antenna);
|
||||
ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
|
||||
} else {
|
||||
sc->sc_rxotherant = 0;
|
||||
}
|
||||
requeue:
|
||||
list_move_tail(&bf->list, &sc->sc_rxbuf);
|
||||
ath_rx_buf_link(sc, bf);
|
||||
} while (1);
|
||||
|
||||
#ifdef CONFIG_SLOW_ANT_DIV
|
||||
if ((rx_status.flags & ATH_RX_RSSI_VALID) &&
|
||||
ieee80211_is_beacon(fc)) {
|
||||
ath_slow_ant_div(&sc->sc_antdiv, hdr, &ds->ds_rxstat);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* For frames successfully indicated, the buffer will be
|
||||
* returned to us by upper layers by calling
|
||||
* ath_rx_mpdu_requeue, either synchronusly or asynchronously.
|
||||
* So we don't want to do it here in this loop.
|
||||
*/
|
||||
continue;
|
||||
|
||||
rx_next:
|
||||
bf->bf_status |= ATH_BUFSTATUS_FREE;
|
||||
} while (TRUE);
|
||||
|
||||
if (chainreset) {
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"%s: Reset rx chain mask. "
|
||||
"Do internal reset\n", __func__);
|
||||
ASSERT(flush == 0);
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_rxbuflock);
|
||||
|
||||
return 0;
|
||||
#undef PA2DESC
|
||||
|
@ -14,10 +14,6 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implementation of transmit path.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
@ -106,21 +102,35 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
||||
ath9k_hw_txstart(ah, txq->axq_qnum);
|
||||
}
|
||||
|
||||
/* Get transmit rate index using rate in Kbps */
|
||||
|
||||
static int ath_tx_findindex(const struct ath9k_rate_table *rt, int rate)
|
||||
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_xmit_status *tx_status)
|
||||
{
|
||||
int i;
|
||||
int ndx = 0;
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
|
||||
for (i = 0; i < rt->rateCount; i++) {
|
||||
if (rt->info[i].rateKbps == rate) {
|
||||
ndx = i;
|
||||
break;
|
||||
}
|
||||
DPRINTF(sc, ATH_DBG_XMIT,
|
||||
"%s: TX complete: skb: %p\n", __func__, skb);
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
|
||||
tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
|
||||
kfree(tx_info_priv);
|
||||
tx_info->rate_driver_data[0] = NULL;
|
||||
}
|
||||
|
||||
return ndx;
|
||||
if (tx_status->flags & ATH_TX_BAR) {
|
||||
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
tx_status->flags &= ~ATH_TX_BAR;
|
||||
}
|
||||
|
||||
if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
|
||||
/* Frame was ACKed */
|
||||
tx_info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
}
|
||||
|
||||
tx_info->status.rates[0].count = tx_status->retries + 1;
|
||||
|
||||
ieee80211_tx_status(hw, skb);
|
||||
}
|
||||
|
||||
/* Check if it's okay to send out aggregates */
|
||||
@ -137,6 +147,19 @@ static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
|
||||
struct ath_beacon_config *conf)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
|
||||
/* fill in beacon config data */
|
||||
|
||||
conf->beacon_interval = hw->conf.beacon_int;
|
||||
conf->listen_interval = 100;
|
||||
conf->dtim_count = 1;
|
||||
conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
|
||||
}
|
||||
|
||||
/* Calculate Atheros packet type from IEEE80211 packet header */
|
||||
|
||||
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
|
||||
@ -162,26 +185,23 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
|
||||
return htype;
|
||||
}
|
||||
|
||||
static bool check_min_rate(struct sk_buff *skb)
|
||||
static bool is_pae(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
bool use_minrate = false;
|
||||
__le16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
||||
if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
|
||||
use_minrate = true;
|
||||
} else if (ieee80211_is_data(fc)) {
|
||||
if (ieee80211_is_data(fc)) {
|
||||
if (ieee80211_is_nullfunc(fc) ||
|
||||
/* Port Access Entity (IEEE 802.1X) */
|
||||
(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
|
||||
use_minrate = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return use_minrate;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int get_hw_crypto_keytype(struct sk_buff *skb)
|
||||
@ -200,56 +220,6 @@ static int get_hw_crypto_keytype(struct sk_buff *skb)
|
||||
return ATH9K_KEY_TYPE_CLEAR;
|
||||
}
|
||||
|
||||
static void setup_rate_retries(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
struct ath_rc_series *rcs;
|
||||
struct ieee80211_hdr *hdr;
|
||||
const struct ath9k_rate_table *rt;
|
||||
bool use_minrate;
|
||||
__le16 fc;
|
||||
u8 rix;
|
||||
|
||||
rt = sc->sc_currates;
|
||||
BUG_ON(!rt);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; /* HACK */
|
||||
rcs = tx_info_priv->rcs;
|
||||
|
||||
/* Check if min rates have to be used */
|
||||
use_minrate = check_min_rate(skb);
|
||||
|
||||
if (ieee80211_is_data(fc) && !use_minrate) {
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
rcs[0].rix =
|
||||
ath_tx_findindex(rt, tx_info_priv->min_rate);
|
||||
/* mcast packets are not re-tried */
|
||||
rcs[0].tries = 1;
|
||||
}
|
||||
} else {
|
||||
/* for management and control frames,
|
||||
or for NULL and EAPOL frames */
|
||||
if (use_minrate)
|
||||
rcs[0].rix = ath_rate_findrateix(sc, tx_info_priv->min_rate);
|
||||
else
|
||||
rcs[0].rix = 0;
|
||||
rcs[0].tries = ATH_MGT_TXMAXTRY;
|
||||
}
|
||||
|
||||
rix = rcs[0].rix;
|
||||
|
||||
if (ieee80211_has_morefrags(fc) ||
|
||||
(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
|
||||
rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
|
||||
rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
|
||||
/* reset tries but keep rate index */
|
||||
rcs[0].tries = ATH_TXMAXTRY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called only when tx aggregation is enabled and HT is supported */
|
||||
|
||||
static void assign_aggr_tid_seqno(struct sk_buff *skb,
|
||||
@ -278,7 +248,7 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb,
|
||||
|
||||
/* Get seqno */
|
||||
|
||||
if (ieee80211_is_data(fc) && !check_min_rate(skb)) {
|
||||
if (ieee80211_is_data(fc) && !is_pae(skb)) {
|
||||
/* For HT capable stations, we save tidno for later use.
|
||||
* We also override seqno set by upper layer with the one
|
||||
* in tx aggregation state.
|
||||
@ -523,27 +493,23 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
* width - 0 for 20 MHz, 1 for 40 MHz
|
||||
* half_gi - to use 4us v/s 3.6 us for symbol time
|
||||
*/
|
||||
|
||||
static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
|
||||
int width, int half_gi, bool shortPreamble)
|
||||
{
|
||||
const struct ath9k_rate_table *rt = sc->sc_currates;
|
||||
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
|
||||
u32 nbits, nsymbits, duration, nsymbols;
|
||||
u8 rc;
|
||||
int streams, pktlen;
|
||||
|
||||
pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
|
||||
rc = rt->info[rix].rateCode;
|
||||
rc = rate_table->info[rix].ratecode;
|
||||
|
||||
/*
|
||||
* for legacy rates, use old function to compute packet duration
|
||||
*/
|
||||
/* for legacy rates, use old function to compute packet duration */
|
||||
if (!IS_HT_RATE(rc))
|
||||
return ath9k_hw_computetxtime(sc->sc_ah, rt, pktlen, rix,
|
||||
shortPreamble);
|
||||
/*
|
||||
* find number of symbols: PLCP + data
|
||||
*/
|
||||
return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
|
||||
rix, shortPreamble);
|
||||
|
||||
/* find number of symbols: PLCP + data */
|
||||
nbits = (pktlen << 3) + OFDM_PLCP_BITS;
|
||||
nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
|
||||
nsymbols = (nbits + nsymbits - 1) / nsymbits;
|
||||
@ -553,9 +519,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
|
||||
else
|
||||
duration = SYMBOL_TIME_HALFGI(nsymbols);
|
||||
|
||||
/*
|
||||
* addup duration for legacy/ht training and signal fields
|
||||
*/
|
||||
/* addup duration for legacy/ht training and signal fields */
|
||||
streams = HT_RC_2_STREAMS(rc);
|
||||
duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
|
||||
|
||||
@ -567,179 +531,125 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
|
||||
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
const struct ath9k_rate_table *rt;
|
||||
struct ath_rate_table *rt;
|
||||
struct ath_desc *ds = bf->bf_desc;
|
||||
struct ath_desc *lastds = bf->bf_lastbf->bf_desc;
|
||||
struct ath9k_11n_rate_series series[4];
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ieee80211_tx_rate *rates;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int i, flags, rtsctsena = 0;
|
||||
u32 ctsduration = 0;
|
||||
u8 rix = 0, cix, ctsrate = 0;
|
||||
struct ath_node *an = NULL;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
__le16 fc;
|
||||
|
||||
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
|
||||
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
rates = tx_info->control.rates;
|
||||
|
||||
if (tx_info->control.sta)
|
||||
an = (struct ath_node *)tx_info->control.sta->drv_priv;
|
||||
if (ieee80211_has_morefrags(fc) ||
|
||||
(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
|
||||
rates[1].count = rates[2].count = rates[3].count = 0;
|
||||
rates[1].idx = rates[2].idx = rates[3].idx = 0;
|
||||
rates[0].count = ATH_TXMAXTRY;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the cix for the lowest valid rix.
|
||||
*/
|
||||
rt = sc->sc_currates;
|
||||
for (i = 4; i--;) {
|
||||
if (bf->bf_rcs[i].tries) {
|
||||
rix = bf->bf_rcs[i].rix;
|
||||
/* get the cix for the lowest valid rix */
|
||||
rt = sc->hw_rate_table[sc->sc_curmode];
|
||||
for (i = 3; i >= 0; i--) {
|
||||
if (rates[i].count && (rates[i].idx >= 0)) {
|
||||
rix = rates[i].idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA));
|
||||
cix = rt->info[rix].controlRate;
|
||||
cix = rt->info[rix].ctrl_rate;
|
||||
|
||||
/*
|
||||
* If 802.11g protection is enabled, determine whether
|
||||
* to use RTS/CTS or just CTS. Note that this is only
|
||||
* done for OFDM/HT unicast frames.
|
||||
* If 802.11g protection is enabled, determine whether to use RTS/CTS or
|
||||
* just CTS. Note that this is only done for OFDM/HT unicast frames.
|
||||
*/
|
||||
if (sc->sc_protmode != PROT_M_NONE &&
|
||||
(rt->info[rix].phy == PHY_OFDM ||
|
||||
rt->info[rix].phy == PHY_HT) &&
|
||||
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
|
||||
if (sc->sc_protmode != PROT_M_NONE && !(bf->bf_flags & ATH9K_TXDESC_NOACK)
|
||||
&& (rt->info[rix].phy == WLAN_RC_PHY_OFDM ||
|
||||
WLAN_RC_PHY_HT(rt->info[rix].phy))) {
|
||||
if (sc->sc_protmode == PROT_M_RTSCTS)
|
||||
flags = ATH9K_TXDESC_RTSENA;
|
||||
else if (sc->sc_protmode == PROT_M_CTSONLY)
|
||||
flags = ATH9K_TXDESC_CTSENA;
|
||||
|
||||
cix = rt->info[sc->sc_protrix].controlRate;
|
||||
cix = rt->info[sc->sc_protrix].ctrl_rate;
|
||||
rtsctsena = 1;
|
||||
}
|
||||
|
||||
/* For 11n, the default behavior is to enable RTS for
|
||||
* hw retried frames. We enable the global flag here and
|
||||
* let rate series flags determine which rates will actually
|
||||
* use RTS.
|
||||
/* For 11n, the default behavior is to enable RTS for hw retried frames.
|
||||
* We enable the global flag here and let rate series flags determine
|
||||
* which rates will actually use RTS.
|
||||
*/
|
||||
if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) {
|
||||
/*
|
||||
* 802.11g protection not needed, use our default behavior
|
||||
*/
|
||||
/* 802.11g protection not needed, use our default behavior */
|
||||
if (!rtsctsena)
|
||||
flags = ATH9K_TXDESC_RTSENA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set protection if aggregate protection on
|
||||
*/
|
||||
/* Set protection if aggregate protection on */
|
||||
if (sc->sc_config.ath_aggr_prot &&
|
||||
(!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
|
||||
flags = ATH9K_TXDESC_RTSENA;
|
||||
cix = rt->info[sc->sc_protrix].controlRate;
|
||||
cix = rt->info[sc->sc_protrix].ctrl_rate;
|
||||
rtsctsena = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For AR5416 - RTS cannot be followed by a frame larger than 8K.
|
||||
*/
|
||||
if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) {
|
||||
/*
|
||||
* Ensure that in the case of SM Dynamic power save
|
||||
* while we are bursting the second aggregate the
|
||||
* RTS is cleared.
|
||||
*/
|
||||
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
|
||||
if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit))
|
||||
flags &= ~(ATH9K_TXDESC_RTSENA);
|
||||
}
|
||||
|
||||
/*
|
||||
* CTS transmit rate is derived from the transmit rate
|
||||
* by looking in the h/w rate table. We must also factor
|
||||
* in whether or not a short preamble is to be used.
|
||||
* NB: cix is set above where RTS/CTS is enabled
|
||||
* CTS transmit rate is derived from the transmit rate by looking in the
|
||||
* h/w rate table. We must also factor in whether or not a short
|
||||
* preamble is to be used. NB: cix is set above where RTS/CTS is enabled
|
||||
*/
|
||||
BUG_ON(cix == 0xff);
|
||||
ctsrate = rt->info[cix].rateCode |
|
||||
(bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0);
|
||||
|
||||
/*
|
||||
* Setup HAL rate series
|
||||
*/
|
||||
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
|
||||
ctsrate = rt->info[cix].ratecode |
|
||||
(bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!bf->bf_rcs[i].tries)
|
||||
if (!rates[i].count || (rates[i].idx < 0))
|
||||
continue;
|
||||
|
||||
rix = bf->bf_rcs[i].rix;
|
||||
rix = rates[i].idx;
|
||||
|
||||
series[i].Rate = rt->info[rix].rateCode |
|
||||
(bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0);
|
||||
series[i].Rate = rt->info[rix].ratecode |
|
||||
(bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0);
|
||||
|
||||
series[i].Tries = bf->bf_rcs[i].tries;
|
||||
series[i].Tries = rates[i].count;
|
||||
|
||||
series[i].RateFlags = (
|
||||
(bf->bf_rcs[i].flags & ATH_RC_RTSCTS_FLAG) ?
|
||||
(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ?
|
||||
ATH9K_RATESERIES_RTS_CTS : 0) |
|
||||
((bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) ?
|
||||
((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ?
|
||||
ATH9K_RATESERIES_2040 : 0) |
|
||||
((bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG) ?
|
||||
((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ?
|
||||
ATH9K_RATESERIES_HALFGI : 0);
|
||||
|
||||
series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
|
||||
(bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
|
||||
(bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
|
||||
(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0,
|
||||
(rates[i].flags & IEEE80211_TX_RC_SHORT_GI),
|
||||
bf_isshpreamble(bf));
|
||||
|
||||
if (bf_isht(bf) && an)
|
||||
series[i].ChSel = ath_chainmask_sel_logic(sc, an);
|
||||
else
|
||||
series[i].ChSel = sc->sc_tx_chainmask;
|
||||
series[i].ChSel = sc->sc_tx_chainmask;
|
||||
|
||||
if (rtsctsena)
|
||||
series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* For non-HT devices, calculate RTS/CTS duration in software
|
||||
* and disable multi-rate retry.
|
||||
*/
|
||||
if (flags && !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)) {
|
||||
/*
|
||||
* Compute the transmit duration based on the frame
|
||||
* size and the size of an ACK frame. We call into the
|
||||
* HAL to do the computation since it depends on the
|
||||
* characteristics of the actual PHY being used.
|
||||
*
|
||||
* NB: CTS is assumed the same size as an ACK so we can
|
||||
* use the precalculated ACK durations.
|
||||
*/
|
||||
if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */
|
||||
ctsduration += bf_isshpreamble(bf) ?
|
||||
rt->info[cix].spAckDuration :
|
||||
rt->info[cix].lpAckDuration;
|
||||
}
|
||||
|
||||
ctsduration += series[0].PktDuration;
|
||||
|
||||
if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */
|
||||
ctsduration += bf_isshpreamble(bf) ?
|
||||
rt->info[rix].spAckDuration :
|
||||
rt->info[rix].lpAckDuration;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable multi-rate retry when using RTS/CTS by clearing
|
||||
* series 1, 2 and 3.
|
||||
*/
|
||||
memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* set dur_update_en for l-sig computation except for PS-Poll frames
|
||||
*/
|
||||
ath9k_hw_set11n_ratescenario(ah, ds, lastds,
|
||||
!bf_ispspoll(bf),
|
||||
ctsrate,
|
||||
ctsduration,
|
||||
/* set dur_update_en for l-sig computation except for PS-Poll frames */
|
||||
ath9k_hw_set11n_ratescenario(ah, ds, lastds, !bf_ispspoll(bf),
|
||||
ctsrate, ctsduration,
|
||||
series, 4, flags);
|
||||
|
||||
if (sc->sc_config.ath_aggr_prot && flags)
|
||||
@ -750,29 +660,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* Function to send a normal HT (non-AMPDU) frame
|
||||
* NB: must be called with txq lock held
|
||||
*/
|
||||
|
||||
static int ath_tx_send_normal(struct ath_softc *sc,
|
||||
struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid,
|
||||
struct list_head *bf_head)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
|
||||
BUG_ON(list_empty(bf_head));
|
||||
|
||||
bf = list_first_entry(bf_head, struct ath_buf, list);
|
||||
bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */
|
||||
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/* XXX: HACK! */
|
||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
|
||||
memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
|
||||
|
||||
/* update starting sequence number for subsequent ADDBA request */
|
||||
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
|
||||
|
||||
@ -1051,18 +950,37 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
||||
return;
|
||||
}
|
||||
|
||||
static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
|
||||
tx_info_priv->update_rc = false;
|
||||
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
|
||||
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
|
||||
if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
|
||||
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
|
||||
if (bf_isdata(bf)) {
|
||||
memcpy(&tx_info_priv->tx, &ds->ds_txstat,
|
||||
sizeof(tx_info_priv->tx));
|
||||
tx_info_priv->n_frames = bf->bf_nframes;
|
||||
tx_info_priv->n_bad_frames = nbad;
|
||||
tx_info_priv->update_rc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Process completed xmit descriptors from the specified queue */
|
||||
|
||||
static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_buf *bf, *lastbf, *bf_held = NULL;
|
||||
struct list_head bf_head;
|
||||
struct ath_desc *ds, *tmp_ds;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
int nacked, txok, nbad = 0, isrifs = 0;
|
||||
struct ath_desc *ds;
|
||||
int txok, nbad = 0;
|
||||
int status;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_QUEUE,
|
||||
@ -1070,7 +988,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
||||
txq->axq_link);
|
||||
|
||||
nacked = 0;
|
||||
for (;;) {
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (list_empty(&txq->axq_q)) {
|
||||
@ -1160,30 +1077,8 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
} else {
|
||||
nbad = ath_tx_num_badfrms(sc, bf, txok);
|
||||
}
|
||||
skb = bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/* XXX: HACK! */
|
||||
tx_info_priv = (struct ath_tx_info_priv *) tx_info->control.vif;
|
||||
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
|
||||
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
|
||||
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
|
||||
if (ds->ds_txstat.ts_status == 0)
|
||||
nacked++;
|
||||
|
||||
if (bf_isdata(bf)) {
|
||||
if (isrifs)
|
||||
tmp_ds = bf->bf_rifslast->bf_desc;
|
||||
else
|
||||
tmp_ds = ds;
|
||||
memcpy(&tx_info_priv->tx,
|
||||
&tmp_ds->ds_txstat,
|
||||
sizeof(tx_info_priv->tx));
|
||||
tx_info_priv->n_frames = bf->bf_nframes;
|
||||
tx_info_priv->n_bad_frames = nbad;
|
||||
}
|
||||
}
|
||||
ath_tx_rc_status(bf, ds, nbad);
|
||||
|
||||
/*
|
||||
* Complete this transmit unit
|
||||
@ -1214,7 +1109,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
ath_txq_schedule(sc, txq);
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
return nacked;
|
||||
}
|
||||
|
||||
static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
|
||||
@ -1254,7 +1148,7 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
if (!ath9k_hw_reset(ah,
|
||||
sc->sc_ah->ah_curchan,
|
||||
sc->sc_ht_info.tx_chan_width,
|
||||
sc->tx_chan_width,
|
||||
sc->sc_tx_chainmask, sc->sc_rx_chainmask,
|
||||
sc->sc_ht_extprotspacing, true, &status)) {
|
||||
|
||||
@ -1307,9 +1201,6 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
|
||||
BUG_ON(list_empty(bf_head));
|
||||
|
||||
@ -1335,12 +1226,6 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
/* XXX: HACK! */
|
||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
|
||||
memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
|
||||
|
||||
/* Add sub-frame to BAW */
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
|
||||
@ -1362,9 +1247,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
|
||||
struct ath_buf *bf,
|
||||
struct ath_atx_tid *tid)
|
||||
{
|
||||
const struct ath9k_rate_table *rt = sc->sc_currates;
|
||||
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ieee80211_tx_rate *rates;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
u32 max_4ms_framelen, frame_length;
|
||||
u16 aggr_limit, legacy = 0, maxampdu;
|
||||
@ -1372,10 +1258,9 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
|
||||
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
tx_info_priv = (struct ath_tx_info_priv *)
|
||||
tx_info->control.vif; /* XXX: HACK! */
|
||||
memcpy(bf->bf_rcs,
|
||||
tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
|
||||
rates = tx_info->control.rates;
|
||||
tx_info_priv =
|
||||
(struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
|
||||
|
||||
/*
|
||||
* Find the lowest frame length among the rate series that will have a
|
||||
@ -1385,14 +1270,14 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
|
||||
max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (bf->bf_rcs[i].tries) {
|
||||
frame_length = bf->bf_rcs[i].max_4ms_framelen;
|
||||
|
||||
if (rt->info[bf->bf_rcs[i].rix].phy != PHY_HT) {
|
||||
if (rates[i].count) {
|
||||
if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
|
||||
legacy = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
frame_length =
|
||||
rate_table->info[rates[i].idx].max_4ms_framelen;
|
||||
max_4ms_framelen = min(max_4ms_framelen, frame_length);
|
||||
}
|
||||
}
|
||||
@ -1431,7 +1316,9 @@ static int ath_compute_num_delims(struct ath_softc *sc,
|
||||
struct ath_buf *bf,
|
||||
u16 frmlen)
|
||||
{
|
||||
const struct ath9k_rate_table *rt = sc->sc_currates;
|
||||
struct ath_rate_table *rt = sc->hw_rate_table[sc->sc_curmode];
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
u32 nsymbits, nsymbols, mpdudensity;
|
||||
u16 minlen;
|
||||
u8 rc, flags, rix;
|
||||
@ -1464,11 +1351,11 @@ static int ath_compute_num_delims(struct ath_softc *sc,
|
||||
if (mpdudensity == 0)
|
||||
return ndelim;
|
||||
|
||||
rix = bf->bf_rcs[0].rix;
|
||||
flags = bf->bf_rcs[0].flags;
|
||||
rc = rt->info[rix].rateCode;
|
||||
width = (flags & ATH_RC_CW40_FLAG) ? 1 : 0;
|
||||
half_gi = (flags & ATH_RC_SGI_FLAG) ? 1 : 0;
|
||||
rix = tx_info->control.rates[0].idx;
|
||||
flags = tx_info->control.rates[0].flags;
|
||||
rc = rt->info[rix].ratecode;
|
||||
width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
|
||||
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
|
||||
|
||||
if (half_gi)
|
||||
nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
|
||||
@ -1510,7 +1397,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
|
||||
u16 aggr_limit = 0, al = 0, bpad = 0,
|
||||
al_delta, h_baw = tid->baw_size / 2;
|
||||
enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
|
||||
int prev_al = 0, is_ds_rate = 0;
|
||||
int prev_al = 0;
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
|
||||
BUG_ON(list_empty(&tid->buf_q));
|
||||
@ -1531,11 +1418,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
|
||||
if (!rl) {
|
||||
aggr_limit = ath_lookup_rate(sc, bf, tid);
|
||||
rl = 1;
|
||||
/*
|
||||
* Is rate dual stream
|
||||
*/
|
||||
is_ds_rate =
|
||||
(bf->bf_rcs[0].flags & ATH_RC_DS_FLAG) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1772,20 +1654,19 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct sk_buff *skb, struct scatterlist *sg,
|
||||
struct sk_buff *skb,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
struct ath_rc_series *rcs;
|
||||
int hdrlen;
|
||||
__le16 fc;
|
||||
|
||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
|
||||
tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_KERNEL);
|
||||
tx_info->rate_driver_data[0] = tx_info_priv;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
rcs = tx_info_priv->rcs;
|
||||
|
||||
ATH_TXBUF_RESET(bf);
|
||||
|
||||
@ -1805,7 +1686,7 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
|
||||
(sc->sc_flags & SC_OP_PREAMBLE_SHORT) ?
|
||||
(bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) :
|
||||
(bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE);
|
||||
(sc->hw->conf.ht.enabled &&
|
||||
(sc->hw->conf.ht.enabled && !is_pae(skb) &&
|
||||
(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ?
|
||||
(bf->bf_state.bf_type |= BUF_HT) :
|
||||
(bf->bf_state.bf_type &= ~BUF_HT);
|
||||
@ -1823,15 +1704,6 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
|
||||
bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
|
||||
}
|
||||
|
||||
/* Rate series */
|
||||
|
||||
setup_rate_retries(sc, skb);
|
||||
|
||||
bf->bf_rcs[0] = rcs[0];
|
||||
bf->bf_rcs[1] = rcs[1];
|
||||
bf->bf_rcs[2] = rcs[2];
|
||||
bf->bf_rcs[3] = rcs[3];
|
||||
|
||||
/* Assign seqno, tidno */
|
||||
|
||||
if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR))
|
||||
@ -1847,7 +1719,6 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
|
||||
|
||||
/* FIXME: tx power */
|
||||
static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct scatterlist *sg, u32 n_sg,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
@ -1876,10 +1747,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
|
||||
bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
|
||||
|
||||
ath9k_hw_filltxdesc(ah, ds,
|
||||
sg_dma_len(sg), /* segment length */
|
||||
true, /* first segment */
|
||||
(n_sg == 1) ? true : false, /* last segment */
|
||||
ds); /* first descriptor */
|
||||
skb->len, /* segment length */
|
||||
true, /* first segment */
|
||||
true, /* last segment */
|
||||
ds); /* first descriptor */
|
||||
|
||||
bf->bf_lastfrm = bf;
|
||||
|
||||
@ -1919,7 +1790,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
struct scatterlist sg;
|
||||
|
||||
/* Check if a tx buffer is available */
|
||||
|
||||
@ -1930,15 +1800,8 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ath_tx_setup_buffer(sc, bf, skb, &sg, txctl);
|
||||
|
||||
/* Setup S/G */
|
||||
|
||||
memset(&sg, 0, sizeof(struct scatterlist));
|
||||
sg_dma_address(&sg) = bf->bf_dmacontext;
|
||||
sg_dma_len(&sg) = skb->len;
|
||||
|
||||
ath_tx_start_dma(sc, bf, &sg, 1, txctl);
|
||||
ath_tx_setup_buffer(sc, bf, skb, txctl);
|
||||
ath_tx_start_dma(sc, bf, txctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l,
|
||||
int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
|
||||
IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
|
||||
addr, bits, mask,
|
||||
unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
|
||||
unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l);
|
||||
return ret;
|
||||
}
|
||||
#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
|
||||
|
@ -886,7 +886,6 @@ struct iwl3945_priv {
|
||||
struct work_struct report_work;
|
||||
struct work_struct request_scan;
|
||||
struct work_struct beacon_update;
|
||||
struct work_struct set_monitor;
|
||||
|
||||
struct tasklet_struct irq_tasklet;
|
||||
|
||||
|
@ -53,6 +53,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
|
||||
* is not compatible with earlier drivers.
|
||||
* This number will also appear in << 8 position of 1st dword of uCode file */
|
||||
#define IWL4965_UCODE_API "-2"
|
||||
#define IWL4965_MODULE_FIRMWARE "iwlwifi-4965" IWL4965_UCODE_API ".ucode"
|
||||
|
||||
|
||||
/* module parameters */
|
||||
@ -661,7 +662,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
|
||||
int txq_id = txq->q.id;
|
||||
|
||||
/* Find out whether to activate Tx queue */
|
||||
int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
|
||||
int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
|
||||
|
||||
/* Set up and activate */
|
||||
iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
|
||||
@ -691,9 +692,10 @@ static const u16 default_queue_to_tx_fifo[] = {
|
||||
static int iwl4965_alive_notify(struct iwl_priv *priv)
|
||||
{
|
||||
u32 a;
|
||||
int i = 0;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
int i, chan;
|
||||
u32 reg_val;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
@ -717,6 +719,17 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
||||
iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
|
||||
priv->scd_bc_tbls.dma >> 10);
|
||||
|
||||
/* Enable DMA channel */
|
||||
for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
|
||||
iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
|
||||
|
||||
/* Update FH chicken bits */
|
||||
reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
|
||||
iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
|
||||
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
|
||||
|
||||
/* Disable chain mode for all queues */
|
||||
iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
|
||||
|
||||
@ -747,7 +760,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
||||
(1 << priv->hw_params.max_txq_num) - 1);
|
||||
|
||||
/* Activate all Tx DMA/FIFO channels */
|
||||
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
|
||||
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
|
||||
|
||||
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
|
||||
|
||||
@ -1909,7 +1922,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
|
||||
ra_tid = BUILD_RAxTID(sta_id, tid);
|
||||
|
||||
/* Modify device's station table to Tx this TID */
|
||||
iwl_sta_modify_enable_tid_tx(priv, sta_id, tid);
|
||||
iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
ret = iwl_grab_nic_access(priv);
|
||||
@ -2025,7 +2038,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
|
||||
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
info->flags |= iwl_is_tx_success(status)?
|
||||
info->flags |= iwl_is_tx_success(status) ?
|
||||
IEEE80211_TX_STAT_ACK : 0;
|
||||
iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
|
||||
/* FIXME: code repetition end */
|
||||
@ -2322,7 +2335,7 @@ static struct iwl_ops iwl4965_ops = {
|
||||
|
||||
struct iwl_cfg iwl4965_agn_cfg = {
|
||||
.name = "4965AGN",
|
||||
.fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode",
|
||||
.fw_name = IWL4965_MODULE_FIRMWARE,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
|
||||
@ -2332,7 +2345,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
||||
};
|
||||
|
||||
/* Module firmware */
|
||||
MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode");
|
||||
MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE);
|
||||
|
||||
module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
|
||||
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
|
||||
|
@ -475,6 +475,9 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
|
||||
case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD:
|
||||
index = IWL_CALIB_TX_IQ_PERD;
|
||||
break;
|
||||
case IWL_PHY_CALIBRATE_BASE_BAND_CMD:
|
||||
index = IWL_CALIB_BASE_BAND;
|
||||
break;
|
||||
default:
|
||||
IWL_ERROR("Unknown calibration notification %d\n",
|
||||
hdr->op_code);
|
||||
@ -697,9 +700,10 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
|
||||
static int iwl5000_alive_notify(struct iwl_priv *priv)
|
||||
{
|
||||
u32 a;
|
||||
int i = 0;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
int i, chan;
|
||||
u32 reg_val;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
@ -722,6 +726,18 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
|
||||
|
||||
iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
|
||||
priv->scd_bc_tbls.dma >> 10);
|
||||
|
||||
/* Enable DMA channel */
|
||||
for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++)
|
||||
iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
|
||||
|
||||
/* Update FH chicken bits */
|
||||
reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
|
||||
iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
|
||||
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
|
||||
|
||||
iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
|
||||
IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
|
||||
iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
|
||||
@ -841,8 +857,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_TX_IQ_PERD);
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
break;
|
||||
case CSR_HW_REV_TYPE_5150:
|
||||
priv->hw_params.calib_init_cfg = 0;
|
||||
@ -969,7 +986,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
|
||||
ra_tid = BUILD_RAxTID(sta_id, tid);
|
||||
|
||||
/* Modify device's station table to Tx this TID */
|
||||
iwl_sta_modify_enable_tid_tx(priv, sta_id, tid);
|
||||
iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
ret = iwl_grab_nic_access(priv);
|
||||
@ -1111,7 +1128,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
|
||||
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
info->flags |= iwl_is_tx_success(status)?
|
||||
info->flags |= iwl_is_tx_success(status) ?
|
||||
IEEE80211_TX_STAT_ACK : 0;
|
||||
iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
|
||||
|
||||
|
@ -281,10 +281,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
|
||||
u32 time_diff;
|
||||
s32 index;
|
||||
struct iwl_traffic_load *tl = NULL;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 tid;
|
||||
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & 0xf;
|
||||
} else
|
||||
@ -773,7 +772,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
int status;
|
||||
u8 retries;
|
||||
int rs_index, index = 0;
|
||||
struct iwl_lq_sta *lq_sta;
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
struct iwl_link_quality_cmd *table;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
|
||||
@ -785,12 +784,12 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
struct iwl_scale_tbl_info tbl_type;
|
||||
struct iwl_scale_tbl_info *curr_tbl, *search_tbl;
|
||||
u8 active_index = 0;
|
||||
__le16 fc = hdr->frame_control;
|
||||
s32 tpt = 0;
|
||||
|
||||
IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");
|
||||
|
||||
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
return;
|
||||
|
||||
/* This packet was aggregated but doesn't carry rate scale info */
|
||||
@ -803,8 +802,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
if (retries > 15)
|
||||
retries = 15;
|
||||
|
||||
lq_sta = (struct iwl_lq_sta *)priv_sta;
|
||||
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
|
||||
!lq_sta->ibss_sta_added)
|
||||
goto out;
|
||||
@ -1675,7 +1672,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
int high_tpt = IWL_INVALID_VALUE;
|
||||
u32 fail_count;
|
||||
s8 scale_action = 0;
|
||||
__le16 fc;
|
||||
u16 rate_mask;
|
||||
u8 update_lq = 0;
|
||||
struct iwl_scale_tbl_info *tbl, *tbl1;
|
||||
@ -1690,13 +1686,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
|
||||
IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
|
||||
|
||||
fc = hdr->frame_control;
|
||||
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) {
|
||||
/* Send management frames and broadcast/multicast data using
|
||||
* lowest rate. */
|
||||
/* TODO: this could probably be improved.. */
|
||||
/* Send management frames and broadcast/multicast data using
|
||||
* lowest rate. */
|
||||
/* TODO: this could probably be improved.. */
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sta || !lq_sta)
|
||||
return;
|
||||
@ -2095,29 +2090,26 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct ieee80211_tx_rate_control *txrc)
|
||||
{
|
||||
|
||||
int i;
|
||||
struct sk_buff *skb = txrc->skb;
|
||||
struct ieee80211_supported_band *sband = txrc->sband;
|
||||
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
|
||||
struct ieee80211_conf *conf = &priv->hw->conf;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
__le16 fc;
|
||||
struct iwl_lq_sta *lq_sta;
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
int rate_idx;
|
||||
|
||||
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
|
||||
|
||||
/* Send management frames and broadcast/multicast data using lowest
|
||||
* rate. */
|
||||
fc = hdr->frame_control;
|
||||
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
|
||||
!sta || !priv_sta) {
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
|
||||
info->control.rates[0].idx = rate_lowest_index(sband, sta);
|
||||
return;
|
||||
}
|
||||
|
||||
lq_sta = (struct iwl_lq_sta *)priv_sta;
|
||||
i = lq_sta->last_txrate_idx;
|
||||
rate_idx = lq_sta->last_txrate_idx;
|
||||
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
|
||||
!lq_sta->ibss_sta_added) {
|
||||
@ -2137,14 +2129,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
||||
}
|
||||
}
|
||||
|
||||
if ((i < 0) || (i > IWL_RATE_COUNT)) {
|
||||
info->control.rates[0].idx = rate_lowest_index(sband, sta);
|
||||
return;
|
||||
}
|
||||
if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT)
|
||||
rate_idx = rate_lowest_index(sband, sta);
|
||||
else if (sband->band == IEEE80211_BAND_5GHZ)
|
||||
rate_idx -= IWL_FIRST_OFDM_RATE;
|
||||
|
||||
if (sband->band == IEEE80211_BAND_5GHZ)
|
||||
i -= IWL_FIRST_OFDM_RATE;
|
||||
info->control.rates[0].idx = i;
|
||||
info->control.rates[0].idx = rate_idx;
|
||||
}
|
||||
|
||||
static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
|
||||
@ -2525,7 +2515,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
|
||||
for (i = 0; i < LQ_SIZE; i++) {
|
||||
desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n"
|
||||
"rate=0x%X\n",
|
||||
lq_sta->active_tbl == i?"*":"x",
|
||||
lq_sta->active_tbl == i ? "*" : "x",
|
||||
lq_sta->lq_info[i].lq_type,
|
||||
lq_sta->lq_info[i].is_SGI,
|
||||
lq_sta->lq_info[i].is_fat,
|
||||
|
@ -466,9 +466,9 @@ static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
|
||||
|
||||
/* Set rate mask*/
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
|
||||
rate_mask = priv->active_rate_basic & 0xF;
|
||||
rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
|
||||
else
|
||||
rate_mask = priv->active_rate_basic & 0xFF0;
|
||||
rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
|
||||
|
||||
/* Find lowest valid rate */
|
||||
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
|
||||
@ -1492,7 +1492,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
||||
hw_rf_kill = 1;
|
||||
|
||||
IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
|
||||
hw_rf_kill ? "disable radio":"enable radio");
|
||||
hw_rf_kill ? "disable radio" : "enable radio");
|
||||
|
||||
/* driver only loads ucode once setting the interface up.
|
||||
* the driver as well won't allow loading if RFKILL is set
|
||||
@ -2224,27 +2224,6 @@ static void iwl_bg_rf_kill(struct work_struct *work)
|
||||
iwl_rfkill_set_hw_state(priv);
|
||||
}
|
||||
|
||||
static void iwl_bg_set_monitor(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work,
|
||||
struct iwl_priv, set_monitor);
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
ret = iwl_set_mode(priv, NL80211_IFTYPE_MONITOR);
|
||||
if (ret) {
|
||||
if (ret == -EAGAIN)
|
||||
IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
|
||||
else
|
||||
IWL_ERROR("iwl_set_mode() failed ret = %d\n", ret);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void iwl_bg_run_time_calib_work(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
@ -2890,16 +2869,43 @@ static void iwl_configure_filter(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mc_list)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
__le32 *filter_flags = &priv->staging_rxon.filter_flags;
|
||||
|
||||
if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
|
||||
IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
|
||||
NL80211_IFTYPE_MONITOR,
|
||||
changed_flags, *total_flags);
|
||||
/* queue work 'cuz mac80211 is holding a lock which
|
||||
* prevents us from issuing (synchronous) f/w cmds */
|
||||
queue_work(priv->workqueue, &priv->set_monitor);
|
||||
IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
|
||||
changed_flags, *total_flags);
|
||||
|
||||
if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
|
||||
if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
|
||||
*filter_flags |= RXON_FILTER_PROMISC_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_PROMISC_MSK;
|
||||
}
|
||||
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
|
||||
if (changed_flags & FIF_ALLMULTI) {
|
||||
if (*total_flags & FIF_ALLMULTI)
|
||||
*filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_CONTROL) {
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
*filter_flags |= RXON_FILTER_CTL2HOST_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
|
||||
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
|
||||
*filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
|
||||
}
|
||||
|
||||
/* We avoid iwl_commit_rxon here to commit the new filter flags
|
||||
* since mac80211 will call ieee80211_hw_config immediately.
|
||||
* (mc_list is not supported at this time). Otherwise, we need to
|
||||
* queue a background iwl_commit_rxon work.
|
||||
*/
|
||||
|
||||
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
|
||||
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
|
||||
}
|
||||
|
||||
@ -3058,49 +3064,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_key_conf *keyconf, const u8 *addr,
|
||||
u32 iv32, u16 *phase1key)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
u8 sta_id = IWL_INVALID_STATION;
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
int i;
|
||||
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
IWL_DEBUG_MAC80211("enter\n");
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iwl_scan_cancel(priv)) {
|
||||
/* cancel scan failed, just live w/ bad key and rely
|
||||
briefly on SW decryption */
|
||||
return;
|
||||
}
|
||||
|
||||
key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
|
||||
cpu_to_le16(phase1key[i]);
|
||||
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key);
|
||||
|
||||
IWL_DEBUG_MAC80211("leave\n");
|
||||
}
|
||||
@ -3239,10 +3207,10 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
IWL_DEBUG_HT("start Rx\n");
|
||||
return iwl_rx_agg_start(priv, sta->addr, tid, *ssn);
|
||||
return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn);
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
IWL_DEBUG_HT("stop Rx\n");
|
||||
return iwl_rx_agg_stop(priv, sta->addr, tid);
|
||||
return iwl_sta_rx_agg_stop(priv, sta->addr, tid);
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
IWL_DEBUG_HT("start Tx\n");
|
||||
return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
|
||||
@ -3256,6 +3224,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_queue_stats *stats)
|
||||
{
|
||||
@ -3694,7 +3663,8 @@ static ssize_t show_power_level(struct device *d,
|
||||
break;
|
||||
}
|
||||
|
||||
p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto");
|
||||
p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
|
||||
"fixed" : "auto");
|
||||
p += sprintf(p, "\tINDEX:%d", level);
|
||||
p += sprintf(p, "\n");
|
||||
return p - buf + 1;
|
||||
@ -3832,7 +3802,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
|
||||
INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
|
||||
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
|
||||
INIT_WORK(&priv->set_monitor, iwl_bg_set_monitor);
|
||||
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
|
||||
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
|
||||
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-rfkill.h"
|
||||
#include "iwl-power.h"
|
||||
#include "iwl-sta.h"
|
||||
|
||||
|
||||
MODULE_DESCRIPTION("iwl core");
|
||||
@ -237,28 +238,6 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_hw_nic_init);
|
||||
|
||||
/**
|
||||
* iwl_clear_stations_table - Clear the driver's station table
|
||||
*
|
||||
* NOTE: This does not clear or otherwise alter the device's station table.
|
||||
*/
|
||||
void iwl_clear_stations_table(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
if (iwl_is_alive(priv) &&
|
||||
!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
|
||||
iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
|
||||
IWL_ERROR("Couldn't clear the station table\n");
|
||||
|
||||
priv->num_stations = 0;
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_clear_stations_table);
|
||||
|
||||
void iwl_reset_qos(struct iwl_priv *priv)
|
||||
{
|
||||
@ -832,6 +811,9 @@ int iwl_setup_mac(struct iwl_priv *priv)
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
hw->wiphy->fw_handles_regulatory = true;
|
||||
|
||||
/* Default value; 4 EDCA QOS priorities */
|
||||
hw->queues = 4;
|
||||
/* queues to support 11n aggregation */
|
||||
|
@ -182,7 +182,6 @@ struct iwl_cfg {
|
||||
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
|
||||
struct ieee80211_ops *hw_ops);
|
||||
void iwl_hw_detect(struct iwl_priv *priv);
|
||||
void iwl_clear_stations_table(struct iwl_priv *priv);
|
||||
void iwl_reset_qos(struct iwl_priv *priv);
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
||||
@ -206,8 +205,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
|
||||
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
||||
void iwl_rx_replenish(struct iwl_priv *priv);
|
||||
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
||||
int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn);
|
||||
int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid);
|
||||
int iwl_rx_queue_restock(struct iwl_priv *priv);
|
||||
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
|
||||
void iwl_rx_allocate(struct iwl_priv *priv);
|
||||
|
@ -574,11 +574,6 @@ struct iwl_hw_params {
|
||||
* iwl4965_mac_ <-- mac80211 callback
|
||||
*
|
||||
****************************************************************************/
|
||||
struct iwl_addsta_cmd;
|
||||
extern int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags);
|
||||
extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
|
||||
int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
|
||||
extern void iwl_update_chain_flags(struct iwl_priv *priv);
|
||||
extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
|
||||
extern const u8 iwl_bcast_addr[ETH_ALEN];
|
||||
@ -700,6 +695,7 @@ enum iwl_calib {
|
||||
IWL_CALIB_LO,
|
||||
IWL_CALIB_TX_IQ,
|
||||
IWL_CALIB_TX_IQ_PERD,
|
||||
IWL_CALIB_BASE_BAND,
|
||||
IWL_CALIB_MAX
|
||||
};
|
||||
|
||||
@ -990,7 +986,6 @@ struct iwl_priv {
|
||||
struct work_struct report_work;
|
||||
struct work_struct request_scan;
|
||||
struct work_struct beacon_update;
|
||||
struct work_struct set_monitor;
|
||||
|
||||
struct tasklet_struct irq_tasklet;
|
||||
|
||||
|
@ -72,7 +72,7 @@
|
||||
* Addresses are offsets from device's PCI hardware base address.
|
||||
*/
|
||||
#define FH_MEM_LOWER_BOUND (0x1000)
|
||||
#define FH_MEM_UPPER_BOUND (0x1EF0)
|
||||
#define FH_MEM_UPPER_BOUND (0x2000)
|
||||
|
||||
/**
|
||||
* Keep-Warm (KW) buffer base address.
|
||||
@ -268,6 +268,8 @@
|
||||
|
||||
#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME (0x00008000)
|
||||
|
||||
#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
|
||||
|
||||
|
||||
/**
|
||||
* Rx Shared Status Registers (RSSR)
|
||||
@ -294,6 +296,13 @@
|
||||
|
||||
#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28
|
||||
|
||||
/* TFDB Area - TFDs buffer table */
|
||||
#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
|
||||
#define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900)
|
||||
#define FH_TFDIB_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x958)
|
||||
#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
|
||||
#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
|
||||
|
||||
/**
|
||||
* Transmit DMA Channel Control/Status Registers (TCSR)
|
||||
*
|
||||
@ -323,6 +332,7 @@
|
||||
#define FH49_TCSR_CHNL_NUM (7)
|
||||
#define FH50_TCSR_CHNL_NUM (8)
|
||||
|
||||
/* TCSR: tx_config register values */
|
||||
#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
|
||||
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
|
||||
#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
|
||||
@ -379,31 +389,18 @@
|
||||
(FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \
|
||||
FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl))
|
||||
|
||||
|
||||
|
||||
#define FH_REGS_LOWER_BOUND (0x1000)
|
||||
#define FH_REGS_UPPER_BOUND (0x2000)
|
||||
|
||||
/* Tx service channels */
|
||||
#define FH_SRVC_CHNL (9)
|
||||
#define FH_SRVC_LOWER_BOUND (FH_REGS_LOWER_BOUND + 0x9C8)
|
||||
#define FH_SRVC_UPPER_BOUND (FH_REGS_LOWER_BOUND + 0x9D0)
|
||||
#define FH_SRVC_CHNL (9)
|
||||
#define FH_SRVC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9C8)
|
||||
#define FH_SRVC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
|
||||
#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
|
||||
(FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
|
||||
|
||||
/* TFDB Area - TFDs buffer table */
|
||||
#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
|
||||
#define FH_TFDIB_LOWER_BOUND (FH_REGS_LOWER_BOUND + 0x900)
|
||||
#define FH_TFDIB_UPPER_BOUND (FH_REGS_LOWER_BOUND + 0x958)
|
||||
#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
|
||||
#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
|
||||
|
||||
/* TCSR: tx_config register values */
|
||||
#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
|
||||
|
||||
#define TFD_QUEUE_SIZE_MAX (256)
|
||||
#define TFD_QUEUE_SIZE_BC_DUP (64)
|
||||
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
|
||||
#define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98)
|
||||
/* Instruct FH to increment the retry count of a packet when
|
||||
* it is brought from the memory to TX-FIFO
|
||||
*/
|
||||
#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002)
|
||||
|
||||
/**
|
||||
* struct iwl_rb_status - reseve buffer status
|
||||
@ -423,9 +420,10 @@ struct iwl_rb_status {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
|
||||
#define TFD_QUEUE_SIZE_MAX (256)
|
||||
#define TFD_QUEUE_SIZE_BC_DUP (64)
|
||||
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
|
||||
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
|
||||
|
||||
#define IWL_NUM_OF_TBS 20
|
||||
|
||||
static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
|
||||
@ -440,7 +438,7 @@ static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
|
||||
* @lo: low [31:0] portion of the dma address of TX buffer
|
||||
* every even is unaligned on 16 bit boundary
|
||||
* @hi_n_len 0-3 [35:32] portion of dma
|
||||
* 4-16 length of the tx buffer
|
||||
* 4-15 length of the tx buffer
|
||||
*/
|
||||
struct iwl_tfd_tb {
|
||||
__le32 lo;
|
||||
@ -453,7 +451,8 @@ struct iwl_tfd_tb {
|
||||
* Transmit Frame Descriptor (TFD)
|
||||
*
|
||||
* @ __reserved1[3] reserved
|
||||
* @ num_tbs 0-5 number of active tbs
|
||||
* @ num_tbs 0-4 number of active tbs
|
||||
* 5 reserved
|
||||
* 6-7 padding (not used)
|
||||
* @ tbs[20] transmit frame buffer descriptors
|
||||
* @ __pad padding
|
||||
@ -473,8 +472,6 @@ struct iwl_tfd_tb {
|
||||
* Tx frame, up to 8 KBytes in size.
|
||||
*
|
||||
* A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
|
||||
*
|
||||
* Bit fields in the control dword (val0):
|
||||
*/
|
||||
struct iwl_tfd {
|
||||
u8 __reserved1[3];
|
||||
@ -485,6 +482,6 @@ struct iwl_tfd {
|
||||
|
||||
|
||||
/* Keep Warm Size */
|
||||
#define IWL_KW_SIZE 0x1000 /*4k */
|
||||
#define IWL_KW_SIZE 0x1000 /* 4k */
|
||||
|
||||
#endif /* !__iwl_fh_h__ */
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "iwl-core.h"
|
||||
|
||||
|
||||
#define IWL_CMD(x) case x : return #x
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
|
||||
const char *get_cmd_string(u8 cmd)
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ static inline int __iwl_poll_bit(const char *f, u32 l,
|
||||
int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout);
|
||||
IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
|
||||
addr, bits, mask,
|
||||
unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
|
||||
unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l);
|
||||
return ret;
|
||||
}
|
||||
#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
|
||||
|
@ -499,49 +499,6 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
|
||||
|
||||
int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
|
||||
CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_agg_start);
|
||||
|
||||
int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
|
||||
CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_agg_stop);
|
||||
|
||||
|
||||
/* Calculate noise level, based on measurements during network silence just
|
||||
* before arriving beacon. This measurement can be done only if we know
|
||||
@ -1017,38 +974,6 @@ static inline int iwl_calc_rssi(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
|
||||
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
}
|
||||
|
||||
static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
|
||||
{
|
||||
/* FIXME: need locking over ps_status ??? */
|
||||
u8 sta_id = iwl_find_station(priv, addr);
|
||||
|
||||
if (sta_id != IWL_INVALID_STATION) {
|
||||
u8 sta_awake = priv->stations[sta_id].
|
||||
ps_status == STA_PS_STATUS_WAKE;
|
||||
|
||||
if (sta_awake && ps_bit)
|
||||
priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
|
||||
else if (!sta_awake && !ps_bit) {
|
||||
iwl_sta_modify_ps_wake(priv, sta_id);
|
||||
priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is necessary only for a number of statistics, see the caller. */
|
||||
static int iwl_is_network_packet(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *header)
|
||||
|
@ -132,7 +132,7 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
static int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags)
|
||||
{
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
@ -180,7 +180,6 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_add_sta);
|
||||
|
||||
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf)
|
||||
@ -464,6 +463,29 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_remove_station);
|
||||
|
||||
/**
|
||||
* iwl_clear_stations_table - Clear the driver's station table
|
||||
*
|
||||
* NOTE: This does not clear or otherwise alter the device's station table.
|
||||
*/
|
||||
void iwl_clear_stations_table(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
if (iwl_is_alive(priv) &&
|
||||
!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
|
||||
iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
|
||||
IWL_ERROR("Couldn't clear the station table\n");
|
||||
|
||||
priv->num_stations = 0;
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_clear_stations_table);
|
||||
|
||||
static int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
@ -703,6 +725,55 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
const u8 *addr, u32 iv32, u16 *phase1key)
|
||||
{
|
||||
u8 sta_id = IWL_INVALID_STATION;
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
int i;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iwl_scan_cancel(priv)) {
|
||||
/* cancel scan failed, just live w/ bad key and rely
|
||||
briefly on SW decryption */
|
||||
return;
|
||||
}
|
||||
|
||||
key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].sta.key.key_flags = key_flags;
|
||||
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
|
||||
cpu_to_le16(phase1key[i]);
|
||||
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_update_tkip_key);
|
||||
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
@ -989,9 +1060,9 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
|
||||
EXPORT_SYMBOL(iwl_get_sta_id);
|
||||
|
||||
/**
|
||||
* iwl_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
|
||||
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
|
||||
*/
|
||||
void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid)
|
||||
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -1004,5 +1075,81 @@ void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid)
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_modify_enable_tid_tx);
|
||||
EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
|
||||
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv,
|
||||
const u8 *addr, int tid, u16 ssn)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
|
||||
CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_rx_agg_start);
|
||||
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
|
||||
CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
|
||||
|
||||
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
}
|
||||
|
||||
void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
|
||||
{
|
||||
/* FIXME: need locking over ps_status ??? */
|
||||
u8 sta_id = iwl_find_station(priv, addr);
|
||||
|
||||
if (sta_id != IWL_INVALID_STATION) {
|
||||
u8 sta_awake = priv->stations[sta_id].
|
||||
ps_status == STA_PS_STATUS_WAKE;
|
||||
|
||||
if (sta_awake && ps_bit)
|
||||
priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
|
||||
else if (!sta_awake && !ps_bit) {
|
||||
iwl_sta_modify_ps_wake(priv, sta_id);
|
||||
priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,9 +47,21 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
const u8 *addr, u32 iv32, u16 *phase1key);
|
||||
|
||||
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
|
||||
void iwl_clear_stations_table(struct iwl_priv *priv);
|
||||
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
|
||||
void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid);
|
||||
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
|
||||
u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
|
||||
int is_ap, u8 flags,
|
||||
struct ieee80211_sta_ht_cap *ht_info);
|
||||
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv,
|
||||
const u8 *addr, int tid, u16 ssn);
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid);
|
||||
void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr);
|
||||
#endif /* __iwl_sta_h__ */
|
||||
|
@ -449,11 +449,6 @@ static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
|
||||
iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
|
||||
txq->q.dma_addr >> 8);
|
||||
|
||||
/* Enable DMA channel, using same id as for TFD queue */
|
||||
iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
|
||||
|
||||
iwl_release_nic_access(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
@ -587,8 +582,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
|
||||
iwl_release_nic_access(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
|
||||
|
||||
/* Alloc and init all Tx queues, including the command queue (#4) */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
|
||||
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
|
||||
@ -618,11 +611,9 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
|
||||
*/
|
||||
void iwl_txq_ctx_stop(struct iwl_priv *priv)
|
||||
{
|
||||
|
||||
int txq_id;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
/* Turn off all Tx DMA fifos */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (iwl_grab_nic_access(priv)) {
|
||||
@ -1498,7 +1489,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
||||
ack = bitmap & (1ULL << i);
|
||||
successes += !!ack;
|
||||
IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
|
||||
ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
|
||||
ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
|
||||
agg->start_idx + i);
|
||||
}
|
||||
|
||||
|
@ -519,7 +519,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
|
||||
|
||||
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
|
||||
|
||||
#define IWL_CMD(x) case x : return #x
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
|
||||
static const char *get_cmd_string(u8 cmd)
|
||||
{
|
||||
@ -1425,9 +1425,9 @@ static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv)
|
||||
|
||||
/* Set rate mask*/
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
|
||||
rate_mask = priv->active_rate_basic & 0xF;
|
||||
rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
|
||||
else
|
||||
rate_mask = priv->active_rate_basic & 0xFF0;
|
||||
rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
|
||||
|
||||
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
|
||||
i = iwl3945_rates[i].next_ieee) {
|
||||
@ -4320,7 +4320,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
|
||||
|
||||
IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
|
||||
"RF_KILL bit toggled to %s.\n",
|
||||
hw_rf_kill ? "disable radio":"enable radio");
|
||||
hw_rf_kill ? "disable radio" : "enable radio");
|
||||
|
||||
/* Queue restart only if RF_KILL switch was set to "kill"
|
||||
* when we loaded driver, and is now set to "enable".
|
||||
@ -5996,24 +5996,6 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
|
||||
iwl3945_rfkill_set_hw_state(priv);
|
||||
}
|
||||
|
||||
static void iwl3945_bg_set_monitor(struct work_struct *work)
|
||||
{
|
||||
struct iwl3945_priv *priv = container_of(work,
|
||||
struct iwl3945_priv, set_monitor);
|
||||
|
||||
IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (!iwl3945_is_ready(priv))
|
||||
IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
|
||||
else
|
||||
if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0)
|
||||
IWL_ERROR("iwl3945_set_mode() failed\n");
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
|
||||
|
||||
static void iwl3945_bg_scan_check(struct work_struct *data)
|
||||
@ -6339,10 +6321,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
|
||||
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
|
||||
/* clear out the station table */
|
||||
iwl3945_clear_stations_table(priv);
|
||||
|
||||
iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
|
||||
priv->assoc_id = 1;
|
||||
iwl3945_add_station(priv, priv->bssid, 0, 0);
|
||||
iwl3945_sync_sta(priv, IWL_STA_ID,
|
||||
(priv->band == IEEE80211_BAND_5GHZ) ?
|
||||
@ -6830,16 +6809,43 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mc_list)
|
||||
{
|
||||
struct iwl3945_priv *priv = hw->priv;
|
||||
__le32 *filter_flags = &priv->staging_rxon.filter_flags;
|
||||
|
||||
if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
|
||||
IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
|
||||
NL80211_IFTYPE_MONITOR,
|
||||
changed_flags, *total_flags);
|
||||
/* queue work 'cuz mac80211 is holding a lock which
|
||||
* prevents us from issuing (synchronous) f/w cmds */
|
||||
queue_work(priv->workqueue, &priv->set_monitor);
|
||||
IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
|
||||
changed_flags, *total_flags);
|
||||
|
||||
if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
|
||||
if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
|
||||
*filter_flags |= RXON_FILTER_PROMISC_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_PROMISC_MSK;
|
||||
}
|
||||
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
|
||||
if (changed_flags & FIF_ALLMULTI) {
|
||||
if (*total_flags & FIF_ALLMULTI)
|
||||
*filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_CONTROL) {
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
*filter_flags |= RXON_FILTER_CTL2HOST_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
|
||||
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
|
||||
*filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
|
||||
}
|
||||
|
||||
/* We avoid iwl_commit_rxon here to commit the new filter flags
|
||||
* since mac80211 will call ieee80211_hw_config immediately.
|
||||
* (mc_list is not supported at this time). Otherwise, we need to
|
||||
* queue a background iwl_commit_rxon work.
|
||||
*/
|
||||
|
||||
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
|
||||
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
|
||||
}
|
||||
|
||||
@ -7715,7 +7721,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
|
||||
INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
|
||||
INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
|
||||
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
|
||||
INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor);
|
||||
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
|
||||
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
|
||||
INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
|
||||
@ -7787,6 +7792,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
|
||||
unsigned long flags;
|
||||
|
||||
/***********************
|
||||
* 1. Allocating HW data
|
||||
* ********************/
|
||||
|
||||
/* Disabling hardware scan means that mac80211 will perform scans
|
||||
* "the hard way", rather than using device's scan. */
|
||||
if (iwl3945_param_disable_hw_scan) {
|
||||
@ -7810,27 +7819,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
|
||||
hw->rate_control_algorithm = "iwl-3945-rs";
|
||||
hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
|
||||
|
||||
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
|
||||
priv = hw->priv;
|
||||
priv->hw = hw;
|
||||
|
||||
priv->pci_dev = pdev;
|
||||
priv->cfg = cfg;
|
||||
|
||||
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
|
||||
hw->rate_control_algorithm = "iwl-3945-rs";
|
||||
hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
|
||||
|
||||
/* Select antenna (may be helpful if only one antenna is connected) */
|
||||
priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
|
||||
#ifdef CONFIG_IWL3945_DEBUG
|
||||
iwl3945_debug_level = iwl3945_param_debug;
|
||||
atomic_set(&priv->restrict_refcnt, 0);
|
||||
#endif
|
||||
priv->retry_rate = 1;
|
||||
|
||||
priv->ibss_beacon = NULL;
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
@ -7841,17 +7847,14 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
hw->wiphy->fw_handles_regulatory = true;
|
||||
|
||||
/* 4 EDCA QOS priorities */
|
||||
hw->queues = 4;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
spin_lock_init(&priv->power_data.lock);
|
||||
spin_lock_init(&priv->sta_lock);
|
||||
spin_lock_init(&priv->hcmd_lock);
|
||||
|
||||
INIT_LIST_HEAD(&priv->free_frames);
|
||||
|
||||
mutex_init(&priv->mutex);
|
||||
/***************************
|
||||
* 2. Initializing PCI bus
|
||||
* *************************/
|
||||
if (pci_enable_device(pdev)) {
|
||||
err = -ENODEV;
|
||||
goto out_ieee80211_free_hw;
|
||||
@ -7859,14 +7862,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
/* Clear the driver's (not device's) station table */
|
||||
iwl3945_clear_stations_table(priv);
|
||||
|
||||
priv->data_retry_limit = -1;
|
||||
priv->ieee_channels = NULL;
|
||||
priv->ieee_rates = NULL;
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
if (!err)
|
||||
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
@ -7880,10 +7875,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
if (err)
|
||||
goto out_pci_disable_device;
|
||||
|
||||
/* We disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
* PCI Tx retries from interfering with C3 CPU state */
|
||||
pci_write_config_byte(pdev, 0x41, 0x00);
|
||||
|
||||
/***********************
|
||||
* 3. Read REV Register
|
||||
* ********************/
|
||||
priv->hw_base = pci_iomap(pdev, 0, 0);
|
||||
if (!priv->hw_base) {
|
||||
err = -ENODEV;
|
||||
@ -7894,51 +7888,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
(unsigned long long) pci_resource_len(pdev, 0));
|
||||
IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
|
||||
|
||||
/* Initialize module parameter values here */
|
||||
|
||||
/* Disable radio (SW RF KILL) via parameter when loading driver */
|
||||
if (iwl3945_param_disable) {
|
||||
set_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
IWL_DEBUG_INFO("Radio disabled.\n");
|
||||
}
|
||||
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
|
||||
|
||||
/* Device-specific setup */
|
||||
if (iwl3945_hw_set_hw_setting(priv)) {
|
||||
IWL_ERROR("failed to set hw settings\n");
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
if (iwl3945_param_qos_enable)
|
||||
priv->qos_data.qos_enable = 1;
|
||||
|
||||
iwl3945_reset_qos(priv);
|
||||
|
||||
priv->qos_data.qos_active = 0;
|
||||
priv->qos_data.qos_cap.val = 0;
|
||||
|
||||
iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
|
||||
iwl3945_setup_deferred_work(priv);
|
||||
iwl3945_setup_rx_handlers(priv);
|
||||
|
||||
priv->rates_mask = IWL_RATES_MASK;
|
||||
/* If power management is turned on, default to AC mode */
|
||||
priv->power_mode = IWL_POWER_AC;
|
||||
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl3945_disable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERROR("failed to create sysfs device attributes\n");
|
||||
goto out_release_irq;
|
||||
}
|
||||
/* We disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
* PCI Tx retries from interfering with C3 CPU state */
|
||||
pci_write_config_byte(pdev, 0x41, 0x00);
|
||||
|
||||
/* nic init */
|
||||
iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
@ -7952,6 +7904,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
IWL_DEBUG_INFO("Failed to init the card\n");
|
||||
goto out_remove_sysfs;
|
||||
}
|
||||
|
||||
/***********************
|
||||
* 4. Read EEPROM
|
||||
* ********************/
|
||||
/* Read the EEPROM */
|
||||
err = iwl3945_eeprom_init(priv);
|
||||
if (err) {
|
||||
@ -7963,10 +7919,57 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
|
||||
SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
|
||||
|
||||
/***********************
|
||||
* 5. Setup HW Constants
|
||||
* ********************/
|
||||
/* Device-specific setup */
|
||||
if (iwl3945_hw_set_hw_setting(priv)) {
|
||||
IWL_ERROR("failed to set hw settings\n");
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
/***********************
|
||||
* 6. Setup priv
|
||||
* ********************/
|
||||
priv->retry_rate = 1;
|
||||
priv->ibss_beacon = NULL;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
spin_lock_init(&priv->power_data.lock);
|
||||
spin_lock_init(&priv->sta_lock);
|
||||
spin_lock_init(&priv->hcmd_lock);
|
||||
|
||||
INIT_LIST_HEAD(&priv->free_frames);
|
||||
mutex_init(&priv->mutex);
|
||||
|
||||
/* Clear the driver's (not device's) station table */
|
||||
iwl3945_clear_stations_table(priv);
|
||||
|
||||
priv->data_retry_limit = -1;
|
||||
priv->ieee_channels = NULL;
|
||||
priv->ieee_rates = NULL;
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
|
||||
if (iwl3945_param_qos_enable)
|
||||
priv->qos_data.qos_enable = 1;
|
||||
|
||||
iwl3945_reset_qos(priv);
|
||||
|
||||
priv->qos_data.qos_active = 0;
|
||||
priv->qos_data.qos_cap.val = 0;
|
||||
|
||||
|
||||
priv->rates_mask = IWL_RATES_MASK;
|
||||
/* If power management is turned on, default to AC mode */
|
||||
priv->power_mode = IWL_POWER_AC;
|
||||
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
|
||||
|
||||
err = iwl3945_init_channel_map(priv);
|
||||
if (err) {
|
||||
IWL_ERROR("initializing regulatory failed: %d\n", err);
|
||||
goto out_remove_sysfs;
|
||||
goto out_release_irq;
|
||||
}
|
||||
|
||||
err = iwl3945_init_geos(priv);
|
||||
@ -7975,16 +7978,58 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
goto out_free_channel_map;
|
||||
}
|
||||
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
|
||||
|
||||
/***********************************
|
||||
* 7. Initialize Module Parameters
|
||||
* **********************************/
|
||||
|
||||
/* Initialize module parameter values here */
|
||||
/* Disable radio (SW RF KILL) via parameter when loading driver */
|
||||
if (iwl3945_param_disable) {
|
||||
set_bit(STATUS_RF_KILL_SW, &priv->status);
|
||||
IWL_DEBUG_INFO("Radio disabled.\n");
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
* 8. Setup Services
|
||||
* ********************/
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl3945_disable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERROR("failed to create sysfs device attributes\n");
|
||||
goto out_free_geos;
|
||||
}
|
||||
|
||||
iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
|
||||
iwl3945_setup_deferred_work(priv);
|
||||
iwl3945_setup_rx_handlers(priv);
|
||||
|
||||
/***********************
|
||||
* 9. Conclude
|
||||
* ********************/
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
||||
/*********************************
|
||||
* 10. Setup and Register mac80211
|
||||
* *******************************/
|
||||
|
||||
err = ieee80211_register_hw(priv->hw);
|
||||
if (err) {
|
||||
IWL_ERROR("Failed to register network device (error %d)\n", err);
|
||||
goto out_free_geos;
|
||||
goto out_remove_sysfs;
|
||||
}
|
||||
|
||||
priv->hw->conf.beacon_int = 100;
|
||||
priv->mac80211_registered = 1;
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
||||
|
||||
err = iwl3945_rfkill_init(priv);
|
||||
if (err)
|
||||
@ -7993,12 +8038,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove_sysfs:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||
out_free_geos:
|
||||
iwl3945_free_geos(priv);
|
||||
out_free_channel_map:
|
||||
iwl3945_free_channel_map(priv);
|
||||
out_remove_sysfs:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||
|
||||
|
||||
out_release_irq:
|
||||
destroy_workqueue(priv->workqueue);
|
||||
|
@ -452,9 +452,9 @@ static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw,
|
||||
hwsim_check_magic(vif);
|
||||
if (conf->changed & IEEE80211_IFCC_BSSID) {
|
||||
DECLARE_MAC_BUF(mac);
|
||||
printk(KERN_DEBUG "%s:%s: BSSID changed: %s\n",
|
||||
printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n",
|
||||
wiphy_name(hw->wiphy), __func__,
|
||||
print_mac(mac, conf->bssid));
|
||||
conf->bssid);
|
||||
memcpy(vp->bssid, conf->bssid, ETH_ALEN);
|
||||
}
|
||||
return 0;
|
||||
@ -612,9 +612,8 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
|
||||
if (!vp->assoc)
|
||||
return;
|
||||
|
||||
printk(KERN_DEBUG "%s:%s: send PS-Poll to %s for aid %d\n",
|
||||
wiphy_name(data->hw->wiphy), __func__,
|
||||
print_mac(buf, vp->bssid), vp->aid);
|
||||
printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n",
|
||||
wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid);
|
||||
|
||||
skb = dev_alloc_skb(sizeof(*pspoll));
|
||||
if (!skb)
|
||||
@ -644,9 +643,8 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
|
||||
if (!vp->assoc)
|
||||
return;
|
||||
|
||||
printk(KERN_DEBUG "%s:%s: send data::nullfunc to %s ps=%d\n",
|
||||
wiphy_name(data->hw->wiphy), __func__,
|
||||
print_mac(buf, vp->bssid), ps);
|
||||
printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n",
|
||||
wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps);
|
||||
|
||||
skb = dev_alloc_skb(sizeof(*hdr));
|
||||
if (!skb)
|
||||
|
@ -84,6 +84,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/ieee80211.h>
|
||||
@ -431,9 +432,9 @@ struct fw_info {
|
||||
};
|
||||
|
||||
const static struct fw_info orinoco_fw[] = {
|
||||
{ "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
|
||||
{ "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
|
||||
{ "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 512 }
|
||||
{ NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
|
||||
{ NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
|
||||
{ "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
|
||||
};
|
||||
|
||||
/* Structure used to access fields in FW
|
||||
@ -487,18 +488,17 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
if (err)
|
||||
goto free;
|
||||
|
||||
if (priv->cached_fw)
|
||||
fw_entry = priv->cached_fw;
|
||||
else {
|
||||
if (!priv->cached_fw) {
|
||||
err = request_firmware(&fw_entry, firmware, priv->dev);
|
||||
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Cannot find firmware %s\n",
|
||||
dev->name, firmware);
|
||||
err = -ENOENT;
|
||||
goto free;
|
||||
}
|
||||
priv->cached_fw = fw_entry;
|
||||
}
|
||||
} else
|
||||
fw_entry = priv->cached_fw;
|
||||
|
||||
hdr = (const struct orinoco_fw_header *) fw_entry->data;
|
||||
|
||||
@ -540,11 +540,9 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
dev->name, hermes_present(hw));
|
||||
|
||||
abort:
|
||||
/* In case of error, assume firmware was bogus and release it */
|
||||
if (err) {
|
||||
priv->cached_fw = NULL;
|
||||
/* If we requested the firmware, release it. */
|
||||
if (!priv->cached_fw)
|
||||
release_firmware(fw_entry);
|
||||
}
|
||||
|
||||
free:
|
||||
kfree(pda);
|
||||
@ -648,34 +646,41 @@ symbol_dl_firmware(struct orinoco_private *priv,
|
||||
int ret;
|
||||
const struct firmware *fw_entry;
|
||||
|
||||
if (request_firmware(&fw_entry, fw->pri_fw,
|
||||
priv->dev) != 0) {
|
||||
printk(KERN_ERR "%s: Cannot find firmware: %s\n",
|
||||
dev->name, fw->pri_fw);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!priv->cached_pri_fw) {
|
||||
if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) {
|
||||
printk(KERN_ERR "%s: Cannot find firmware: %s\n",
|
||||
dev->name, fw->pri_fw);
|
||||
return -ENOENT;
|
||||
}
|
||||
} else
|
||||
fw_entry = priv->cached_pri_fw;
|
||||
|
||||
/* Load primary firmware */
|
||||
ret = symbol_dl_image(priv, fw, fw_entry->data,
|
||||
fw_entry->data + fw_entry->size, 0);
|
||||
release_firmware(fw_entry);
|
||||
|
||||
if (!priv->cached_pri_fw)
|
||||
release_firmware(fw_entry);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: Primary firmware download failed\n",
|
||||
dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (request_firmware(&fw_entry, fw->sta_fw,
|
||||
priv->dev) != 0) {
|
||||
printk(KERN_ERR "%s: Cannot find firmware: %s\n",
|
||||
dev->name, fw->sta_fw);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!priv->cached_fw) {
|
||||
if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) {
|
||||
printk(KERN_ERR "%s: Cannot find firmware: %s\n",
|
||||
dev->name, fw->sta_fw);
|
||||
return -ENOENT;
|
||||
}
|
||||
} else
|
||||
fw_entry = priv->cached_fw;
|
||||
|
||||
/* Load secondary firmware */
|
||||
ret = symbol_dl_image(priv, fw, fw_entry->data,
|
||||
fw_entry->data + fw_entry->size, 1);
|
||||
release_firmware(fw_entry);
|
||||
if (!priv->cached_fw)
|
||||
release_firmware(fw_entry);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: Secondary firmware download failed\n",
|
||||
dev->name);
|
||||
@ -708,6 +713,45 @@ static int orinoco_download(struct orinoco_private *priv)
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
|
||||
static void orinoco_cache_fw(struct orinoco_private *priv, int ap)
|
||||
{
|
||||
const struct firmware *fw_entry = NULL;
|
||||
const char *pri_fw;
|
||||
const char *fw;
|
||||
|
||||
pri_fw = orinoco_fw[priv->firmware_type].pri_fw;
|
||||
if (ap)
|
||||
fw = orinoco_fw[priv->firmware_type].ap_fw;
|
||||
else
|
||||
fw = orinoco_fw[priv->firmware_type].sta_fw;
|
||||
|
||||
if (pri_fw) {
|
||||
if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0)
|
||||
priv->cached_pri_fw = fw_entry;
|
||||
}
|
||||
|
||||
if (fw) {
|
||||
if (request_firmware(&fw_entry, fw, priv->dev) == 0)
|
||||
priv->cached_fw = fw_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static void orinoco_uncache_fw(struct orinoco_private *priv)
|
||||
{
|
||||
if (priv->cached_pri_fw)
|
||||
release_firmware(priv->cached_pri_fw);
|
||||
if (priv->cached_fw)
|
||||
release_firmware(priv->cached_fw);
|
||||
|
||||
priv->cached_pri_fw = NULL;
|
||||
priv->cached_fw = NULL;
|
||||
}
|
||||
#else
|
||||
#define orinoco_cache_fw(priv, ap)
|
||||
#define orinoco_uncache_fw(priv)
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
/* Device methods */
|
||||
/********************************************************************/
|
||||
@ -809,7 +853,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
|
||||
wstats->qual.qual = (int)le16_to_cpu(cq.qual);
|
||||
wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
|
||||
wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
|
||||
wstats->qual.updated = 7;
|
||||
wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1168,7 +1212,7 @@ static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
|
||||
wstats.level = level - 0x95;
|
||||
wstats.noise = noise - 0x95;
|
||||
wstats.qual = (level > noise) ? (level - noise) : 0;
|
||||
wstats.updated = 7;
|
||||
wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
|
||||
/* Update spy records */
|
||||
wireless_spy_update(dev, mac, &wstats);
|
||||
}
|
||||
@ -3061,6 +3105,50 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/* Power management */
|
||||
/********************************************************************/
|
||||
#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
|
||||
static int orinoco_pm_notifier(struct notifier_block *notifier,
|
||||
unsigned long pm_event,
|
||||
void *unused)
|
||||
{
|
||||
struct orinoco_private *priv = container_of(notifier,
|
||||
struct orinoco_private,
|
||||
pm_notifier);
|
||||
|
||||
/* All we need to do is cache the firmware before suspend, and
|
||||
* release it when we come out.
|
||||
*
|
||||
* Only need to do this if we're downloading firmware. */
|
||||
if (!priv->do_fw_download)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
switch (pm_event) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
orinoco_cache_fw(priv, 0);
|
||||
break;
|
||||
|
||||
case PM_POST_RESTORE:
|
||||
/* Restore from hibernation failed. We need to clean
|
||||
* up in exactly the same way, so fall through. */
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_SUSPEND:
|
||||
orinoco_uncache_fw(priv);
|
||||
break;
|
||||
|
||||
case PM_RESTORE_PREPARE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
|
||||
#define orinoco_pm_notifier NULL
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
/* Initialization */
|
||||
/********************************************************************/
|
||||
@ -3304,6 +3392,10 @@ static int orinoco_init(struct net_device *dev)
|
||||
}
|
||||
|
||||
if (priv->do_fw_download) {
|
||||
#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
|
||||
orinoco_cache_fw(priv, 0);
|
||||
#endif
|
||||
|
||||
err = orinoco_download(priv);
|
||||
if (err)
|
||||
priv->do_fw_download = 0;
|
||||
@ -3540,8 +3632,13 @@ struct net_device
|
||||
netif_carrier_off(dev);
|
||||
priv->last_linkstatus = 0xffff;
|
||||
|
||||
priv->cached_pri_fw = NULL;
|
||||
priv->cached_fw = NULL;
|
||||
|
||||
/* Register PM notifiers */
|
||||
priv->pm_notifier.notifier_call = orinoco_pm_notifier;
|
||||
register_pm_notifier(&priv->pm_notifier);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@ -3553,9 +3650,10 @@ void free_orinocodev(struct net_device *dev)
|
||||
* when we call tasklet_kill it will run one final time,
|
||||
* emptying the list */
|
||||
tasklet_kill(&priv->rx_tasklet);
|
||||
if (priv->cached_fw)
|
||||
release_firmware(priv->cached_fw);
|
||||
priv->cached_fw = NULL;
|
||||
|
||||
unregister_pm_notifier(&priv->pm_notifier);
|
||||
orinoco_uncache_fw(priv);
|
||||
|
||||
priv->wpa_ie_len = 0;
|
||||
kfree(priv->wpa_ie);
|
||||
orinoco_mic_free(priv);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define DRIVER_VERSION "0.15"
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/iw_handler.h>
|
||||
@ -167,8 +168,11 @@ struct orinoco_private {
|
||||
unsigned int tkip_cm_active:1;
|
||||
unsigned int key_mgmt:3;
|
||||
|
||||
/* Cached in memory firmware to use in ->resume */
|
||||
/* Cached in memory firmware to use during ->resume. */
|
||||
const struct firmware *cached_pri_fw;
|
||||
const struct firmware *cached_fw;
|
||||
|
||||
struct notifier_block pm_notifier;
|
||||
};
|
||||
|
||||
#ifdef ORINOCO_DEBUG
|
||||
|
@ -450,10 +450,29 @@ spectrum_cs_resume(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
struct orinoco_private *priv = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
err = orinoco_reinit_firmware(dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
|
||||
dev->name, err);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
netif_device_attach(dev);
|
||||
priv->hw_unavailable--;
|
||||
schedule_work(&priv->reset_work);
|
||||
|
||||
if (priv->open && !priv->hw_unavailable) {
|
||||
err = __orinoco_up(dev);
|
||||
if (err)
|
||||
printk(KERN_ERR "%s: Error %d restarting card\n",
|
||||
dev->name, err);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -102,6 +102,9 @@ struct p54_common {
|
||||
unsigned int output_power;
|
||||
u32 tsf_low32;
|
||||
u32 tsf_high32;
|
||||
u64 basic_rate_mask;
|
||||
u16 wakeup_timer;
|
||||
u16 aid;
|
||||
struct ieee80211_tx_queue_stats tx_stats[8];
|
||||
struct p54_edcf_queue_param qos_params[8];
|
||||
struct ieee80211_low_level_stats stats;
|
||||
|
@ -530,6 +530,8 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
rx_status.noise = priv->noise;
|
||||
/* XX correct? */
|
||||
rx_status.qual = (100 * hdr->rssi) / 127;
|
||||
if (hdr->rate & 0x10)
|
||||
rx_status.flag |= RX_FLAG_SHORTPRE;
|
||||
rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ?
|
||||
hdr->rate : (hdr->rate - 4)) & 0xf;
|
||||
rx_status.freq = freq;
|
||||
@ -576,7 +578,7 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
unsigned long flags;
|
||||
u32 freed = 0, last_addr = priv->rx_start;
|
||||
|
||||
if (!skb || !dev)
|
||||
if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_queue.lock, flags);
|
||||
@ -1058,6 +1060,7 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
|
||||
*aid = 0;
|
||||
*queue = 3;
|
||||
@ -1198,7 +1201,10 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
txhdr->key_type = 0;
|
||||
txhdr->key_len = 0;
|
||||
txhdr->hw_queue = queue;
|
||||
txhdr->backlog = 32;
|
||||
if (current_queue)
|
||||
txhdr->backlog = current_queue->len;
|
||||
else
|
||||
txhdr->backlog = 0;
|
||||
memset(txhdr->durations, 0, sizeof(txhdr->durations));
|
||||
txhdr->tx_antenna = (info->antenna_sel_tx == 0) ?
|
||||
2 : info->antenna_sel_tx - 1;
|
||||
@ -1243,20 +1249,20 @@ static int p54_setup_mac(struct ieee80211_hw *dev, u16 mode, const u8 *bssid)
|
||||
setup->rx_antenna = priv->rx_antenna;
|
||||
setup->rx_align = 0;
|
||||
if (priv->fw_var < 0x500) {
|
||||
setup->v1.basic_rate_mask = cpu_to_le32(0x15f);
|
||||
setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
|
||||
memset(setup->v1.rts_rates, 0, 8);
|
||||
setup->v1.rx_addr = cpu_to_le32(priv->rx_end);
|
||||
setup->v1.max_rx = cpu_to_le16(priv->rx_mtu);
|
||||
setup->v1.rxhw = cpu_to_le16(priv->rxhw);
|
||||
setup->v1.wakeup_timer = cpu_to_le16(500);
|
||||
setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer);
|
||||
setup->v1.unalloc0 = cpu_to_le16(0);
|
||||
} else {
|
||||
setup->v2.rx_addr = cpu_to_le32(priv->rx_end);
|
||||
setup->v2.max_rx = cpu_to_le16(priv->rx_mtu);
|
||||
setup->v2.rxhw = cpu_to_le16(priv->rxhw);
|
||||
setup->v2.timer = cpu_to_le16(1000);
|
||||
setup->v2.timer = cpu_to_le16(priv->wakeup_timer);
|
||||
setup->v2.truncate = cpu_to_le16(48896);
|
||||
setup->v2.basic_rate_mask = cpu_to_le32(0x15f);
|
||||
setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
|
||||
setup->v2.sbss_offset = 0;
|
||||
setup->v2.mcast_window = 0;
|
||||
setup->v2.rx_rssi_threshold = 0;
|
||||
@ -1342,7 +1348,7 @@ static int p54_set_freq(struct ieee80211_hw *dev, u16 frequency)
|
||||
} else {
|
||||
chan->v2.rssical_mul = cpu_to_le16(130);
|
||||
chan->v2.rssical_add = cpu_to_le16(0xfe70);
|
||||
chan->v2.basic_rate_mask = cpu_to_le32(0x15f);
|
||||
chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
|
||||
memset(chan->v2.rts_rates, 0, 8);
|
||||
}
|
||||
priv->tx(dev, skb, 1);
|
||||
@ -1518,16 +1524,24 @@ static int p54_start(struct ieee80211_hw *dev)
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
err = priv->open(dev);
|
||||
if (!err)
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
if (err)
|
||||
goto out;
|
||||
P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
|
||||
P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
|
||||
P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
|
||||
P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
|
||||
err = p54_set_edcf(dev);
|
||||
if (!err)
|
||||
err = p54_init_stats(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
err = p54_init_stats(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
err = p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return err;
|
||||
}
|
||||
@ -1547,7 +1561,6 @@ static void p54_stop(struct ieee80211_hw *dev)
|
||||
while ((skb = skb_dequeue(&priv->tx_queue)))
|
||||
kfree_skb(skb);
|
||||
|
||||
kfree(priv->cached_beacon);
|
||||
priv->cached_beacon = NULL;
|
||||
priv->stop(dev);
|
||||
priv->tsf_high32 = priv->tsf_low32 = 0;
|
||||
@ -1570,6 +1583,7 @@ static int p54_add_interface(struct ieee80211_hw *dev,
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
priv->mode = conf->type;
|
||||
break;
|
||||
default:
|
||||
@ -1589,6 +1603,7 @@ static int p54_add_interface(struct ieee80211_hw *dev,
|
||||
p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL);
|
||||
break;
|
||||
default:
|
||||
@ -1653,6 +1668,7 @@ static int p54_config_interface(struct ieee80211_hw *dev,
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
|
||||
ret = p54_set_freq(dev, dev->conf.channel->center_freq);
|
||||
if (ret)
|
||||
@ -1712,10 +1728,9 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
|
||||
if ((params) && !(queue > 4)) {
|
||||
P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
|
||||
params->cw_min, params->cw_max, params->txop);
|
||||
ret = p54_set_edcf(dev);
|
||||
} else
|
||||
ret = -EINVAL;
|
||||
if (!ret)
|
||||
ret = p54_set_edcf(dev);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
@ -1792,6 +1807,24 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
|
||||
priv->use_short_slot = info->use_short_slot;
|
||||
p54_set_edcf(dev);
|
||||
}
|
||||
if (changed & BSS_CHANGED_BASIC_RATES) {
|
||||
if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
|
||||
priv->basic_rate_mask = (info->basic_rates << 4);
|
||||
else
|
||||
priv->basic_rate_mask = info->basic_rates;
|
||||
p54_setup_mac(dev, priv->mac_mode, priv->bssid);
|
||||
if (priv->fw_var >= 0x500)
|
||||
p54_set_freq(dev, dev->conf.channel->center_freq);
|
||||
}
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
if (info->assoc) {
|
||||
priv->aid = info->aid;
|
||||
priv->wakeup_timer = info->beacon_int *
|
||||
info->dtim_period * 5;
|
||||
p54_setup_mac(dev, priv->mac_mode, priv->bssid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops p54_ops = {
|
||||
@ -1821,14 +1854,16 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
||||
|
||||
priv = dev->priv;
|
||||
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
|
||||
priv->basic_rate_mask = 0x15f;
|
||||
skb_queue_head_init(&priv->tx_queue);
|
||||
dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
|
||||
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION |
|
||||
NL80211_IFTYPE_ADHOC |
|
||||
NL80211_IFTYPE_AP);
|
||||
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
|
||||
dev->channel_change_time = 1000; /* TODO: find actual value */
|
||||
priv->tx_stats[0].limit = 1; /* Beacon queue */
|
||||
|
@ -259,7 +259,7 @@ enum p54_rx_decrypt_status {
|
||||
P54_DECRYPT_NOCKIPMIC,
|
||||
P54_DECRYPT_FAIL_WEP,
|
||||
P54_DECRYPT_FAIL_TKIP,
|
||||
P54_DECRYPT_FAIL_MICAHEL,
|
||||
P54_DECRYPT_FAIL_MICHAEL,
|
||||
P54_DECRYPT_FAIL_CKIPKP,
|
||||
P54_DECRYPT_FAIL_CKIPMIC,
|
||||
P54_DECRYPT_FAIL_AESCCMP
|
||||
|
@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(pci, p54p_table);
|
||||
static int p54p_upload_firmware(struct ieee80211_hw *dev)
|
||||
{
|
||||
struct p54p_priv *priv = dev->priv;
|
||||
const struct firmware *fw_entry = NULL;
|
||||
__le32 reg;
|
||||
int err;
|
||||
__le32 *data;
|
||||
@ -73,23 +72,15 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
|
||||
P54P_WRITE(ctrl_stat, reg);
|
||||
wmb();
|
||||
|
||||
err = request_firmware(&fw_entry, "isl3886pci", &priv->pdev->dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s (p54pci): cannot find firmware "
|
||||
"(isl3886pci)\n", pci_name(priv->pdev));
|
||||
err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/* wait for the firmware to reset properly */
|
||||
mdelay(10);
|
||||
|
||||
err = p54_parse_firmware(dev, fw_entry);
|
||||
if (err) {
|
||||
release_firmware(fw_entry);
|
||||
err = p54_parse_firmware(dev, priv->firmware);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
data = (__le32 *) fw_entry->data;
|
||||
remains = fw_entry->size;
|
||||
data = (__le32 *) priv->firmware->data;
|
||||
remains = priv->firmware->size;
|
||||
device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
|
||||
while (remains) {
|
||||
u32 i = 0;
|
||||
@ -107,8 +98,6 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
|
||||
P54P_READ(int_enable);
|
||||
}
|
||||
|
||||
release_firmware(fw_entry);
|
||||
|
||||
reg = P54P_READ(ctrl_stat);
|
||||
reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
|
||||
reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
|
||||
@ -500,15 +489,14 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
if (mem_len < sizeof(struct p54p_csr)) {
|
||||
printk(KERN_ERR "%s (p54pci): Too short PCI resources\n",
|
||||
pci_name(pdev));
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
goto err_disable_dev;
|
||||
}
|
||||
|
||||
err = pci_request_regions(pdev, "p54pci");
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n",
|
||||
pci_name(pdev));
|
||||
return err;
|
||||
goto err_disable_dev;
|
||||
}
|
||||
|
||||
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
|
||||
@ -561,6 +549,17 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
spin_lock_init(&priv->lock);
|
||||
tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
|
||||
|
||||
err = request_firmware(&priv->firmware, "isl3886pci",
|
||||
&priv->pdev->dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s (p54pci): cannot find firmware "
|
||||
"(isl3886pci)\n", pci_name(priv->pdev));
|
||||
err = request_firmware(&priv->firmware, "isl3886",
|
||||
&priv->pdev->dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
}
|
||||
|
||||
err = p54p_open(dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
@ -579,6 +578,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
return 0;
|
||||
|
||||
err_free_common:
|
||||
release_firmware(priv->firmware);
|
||||
p54_free_common(dev);
|
||||
pci_free_consistent(pdev, sizeof(*priv->ring_control),
|
||||
priv->ring_control, priv->ring_control_dma);
|
||||
@ -592,6 +592,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
|
||||
err_free_reg:
|
||||
pci_release_regions(pdev);
|
||||
err_disable_dev:
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
}
|
||||
@ -606,6 +607,7 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
|
||||
|
||||
ieee80211_unregister_hw(dev);
|
||||
priv = dev->priv;
|
||||
release_firmware(priv->firmware);
|
||||
pci_free_consistent(pdev, sizeof(*priv->ring_control),
|
||||
priv->ring_control, priv->ring_control_dma);
|
||||
p54_free_common(dev);
|
||||
|
@ -93,7 +93,7 @@ struct p54p_priv {
|
||||
struct pci_dev *pdev;
|
||||
struct p54p_csr __iomem *map;
|
||||
struct tasklet_struct rx_tasklet;
|
||||
|
||||
const struct firmware *firmware;
|
||||
spinlock_t lock;
|
||||
struct p54p_ring_control *ring_control;
|
||||
dma_addr_t ring_control_dma;
|
||||
|
@ -49,20 +49,10 @@
|
||||
* the access attempt is considered to have failed,
|
||||
* and we will print an error.
|
||||
*/
|
||||
static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, BBPCSR, ®);
|
||||
if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
break;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
#define WAIT_FOR_BBP(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
|
||||
#define WAIT_FOR_RF(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
|
||||
|
||||
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u8 value)
|
||||
@ -72,31 +62,20 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
reg = rt2400pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
|
||||
|
||||
/*
|
||||
* Write the data into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n");
|
||||
}
|
||||
|
||||
static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
@ -107,74 +86,54 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the read request into the register.
|
||||
* After the data has been written, we wait until hardware
|
||||
* returns the correct value, if at any time the register
|
||||
* doesn't become available in time, reg will be 0xffffffff
|
||||
* which means we return 0xff to the caller.
|
||||
*/
|
||||
reg = rt2400pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
|
||||
|
||||
/*
|
||||
* Write the request into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
*/
|
||||
reg = rt2400pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
goto exit_fail;
|
||||
WAIT_FOR_BBP(rt2x00dev, ®);
|
||||
}
|
||||
|
||||
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
|
||||
*value = 0xff;
|
||||
}
|
||||
|
||||
static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u32 value)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, RFCSR, ®);
|
||||
if (!rt2x00_get_field32(reg, RFCSR_BUSY))
|
||||
goto rf_write;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
/*
|
||||
* Wait until the RF becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
if (WAIT_FOR_RF(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, RFCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
|
||||
rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, RFCSR_BUSY, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n");
|
||||
return;
|
||||
|
||||
rf_write:
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, RFCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
|
||||
rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, RFCSR_BUSY, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
}
|
||||
|
||||
|
@ -49,20 +49,10 @@
|
||||
* the access attempt is considered to have failed,
|
||||
* and we will print an error.
|
||||
*/
|
||||
static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, BBPCSR, ®);
|
||||
if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
break;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
#define WAIT_FOR_BBP(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
|
||||
#define WAIT_FOR_RF(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
|
||||
|
||||
static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u8 value)
|
||||
@ -72,31 +62,20 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
reg = rt2500pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
|
||||
|
||||
/*
|
||||
* Write the data into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n");
|
||||
}
|
||||
|
||||
static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
@ -107,74 +86,54 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the read request into the register.
|
||||
* After the data has been written, we wait until hardware
|
||||
* returns the correct value, if at any time the register
|
||||
* doesn't become available in time, reg will be 0xffffffff
|
||||
* which means we return 0xff to the caller.
|
||||
*/
|
||||
reg = rt2500pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
|
||||
|
||||
/*
|
||||
* Write the request into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
*/
|
||||
reg = rt2500pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, BBPCSR_BUSY))
|
||||
goto exit_fail;
|
||||
WAIT_FOR_BBP(rt2x00dev, ®);
|
||||
}
|
||||
|
||||
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
|
||||
*value = 0xff;
|
||||
}
|
||||
|
||||
static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u32 value)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, RFCSR, ®);
|
||||
if (!rt2x00_get_field32(reg, RFCSR_BUSY))
|
||||
goto rf_write;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
/*
|
||||
* Wait until the RF becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
if (WAIT_FOR_RF(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, RFCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
|
||||
rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, RFCSR_BUSY, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n");
|
||||
return;
|
||||
|
||||
rf_write:
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, RFCSR_VALUE, value);
|
||||
rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
|
||||
rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, RFCSR_BUSY, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
|
||||
__le16 reg;
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
®, sizeof(u16), REGISTER_TIMEOUT);
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
*value = le16_to_cpu(reg);
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
||||
__le16 reg;
|
||||
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
®, sizeof(u16), REGISTER_TIMEOUT);
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
*value = le16_to_cpu(reg);
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
|
||||
__le16 reg = cpu_to_le16(value);
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
®, sizeof(u16), REGISTER_TIMEOUT);
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
||||
@ -99,7 +99,7 @@ static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
||||
__le16 reg = cpu_to_le16(value);
|
||||
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
®, sizeof(u16), REGISTER_TIMEOUT);
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||
@ -112,21 +112,32 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||
REGISTER_TIMEOUT16(length));
|
||||
}
|
||||
|
||||
static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
|
||||
static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
struct rt2x00_field16 field,
|
||||
u16 *reg)
|
||||
{
|
||||
u16 reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®);
|
||||
if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
|
||||
break;
|
||||
rt2500usb_register_read_lock(rt2x00dev, offset, reg);
|
||||
if (!rt2x00_get_field16(*reg, field))
|
||||
return 1;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
return reg;
|
||||
ERROR(rt2x00dev, "Indirect register access failed: "
|
||||
"offset=0x%.08x, value=0x%.08x\n", offset, *reg);
|
||||
*reg = ~0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WAIT_FOR_BBP(__dev, __reg) \
|
||||
rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg))
|
||||
#define WAIT_FOR_RF(__dev, __reg) \
|
||||
rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg))
|
||||
|
||||
static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u8 value)
|
||||
{
|
||||
@ -135,30 +146,19 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
reg = rt2500usb_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR7_DATA, value);
|
||||
rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
|
||||
rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0);
|
||||
|
||||
/*
|
||||
* Write the data into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR7_DATA, value);
|
||||
rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
|
||||
rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0);
|
||||
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
|
||||
}
|
||||
|
||||
static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
@ -169,78 +169,58 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the read request into the register.
|
||||
* After the data has been written, we wait until hardware
|
||||
* returns the correct value, if at any time the register
|
||||
* doesn't become available in time, reg will be 0xffffffff
|
||||
* which means we return 0xff to the caller.
|
||||
*/
|
||||
reg = rt2500usb_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
|
||||
rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1);
|
||||
|
||||
/*
|
||||
* Write the request into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
|
||||
rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1);
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
|
||||
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®))
|
||||
rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
*/
|
||||
reg = rt2500usb_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
|
||||
goto exit_fail;
|
||||
|
||||
rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®);
|
||||
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
|
||||
*value = 0xff;
|
||||
}
|
||||
|
||||
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u32 value)
|
||||
{
|
||||
u16 reg;
|
||||
unsigned int i;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®);
|
||||
if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
|
||||
goto rf_write;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
/*
|
||||
* Wait until the RF becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
if (WAIT_FOR_RF(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value);
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
|
||||
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16);
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0);
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1);
|
||||
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
|
||||
return;
|
||||
|
||||
rf_write:
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value);
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
|
||||
|
||||
reg = 0;
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16);
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0);
|
||||
rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1);
|
||||
|
||||
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
}
|
||||
|
||||
@ -1128,7 +1108,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
|
||||
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
|
||||
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
int pipe = usb_sndbulkpipe(usb_dev, 1);
|
||||
int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
|
||||
int length;
|
||||
u16 reg;
|
||||
|
||||
@ -1154,7 +1134,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
|
||||
* length of the data to usb_fill_bulk_urb. Pass the skb
|
||||
* to the driver to determine what the length should be.
|
||||
*/
|
||||
length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb);
|
||||
length = rt2x00dev->ops->lib->get_tx_data_len(entry);
|
||||
|
||||
usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
|
||||
entry->skb->data, length, rt2500usb_beacondone,
|
||||
@ -1176,8 +1156,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
|
||||
usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
|
||||
struct sk_buff *skb)
|
||||
static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
|
||||
{
|
||||
int length;
|
||||
|
||||
@ -1185,8 +1164,8 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
|
||||
* The length _must_ be a multiple of 2,
|
||||
* but it must _not_ be a multiple of the USB packet size.
|
||||
*/
|
||||
length = roundup(skb->len, 2);
|
||||
length += (2 * !(length % rt2x00dev->usb_maxpacket));
|
||||
length = roundup(entry->skb->len, 2);
|
||||
length += (2 * !(length % entry->queue->usb_maxpacket));
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -555,8 +555,7 @@ struct rt2x00lib_ops {
|
||||
struct txentry_desc *txdesc);
|
||||
int (*write_tx_data) (struct queue_entry *entry);
|
||||
void (*write_beacon) (struct queue_entry *entry);
|
||||
int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
|
||||
struct sk_buff *skb);
|
||||
int (*get_tx_data_len) (struct queue_entry *entry);
|
||||
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
|
||||
const enum data_queue_qid queue);
|
||||
|
||||
@ -798,11 +797,6 @@ struct rt2x00_dev {
|
||||
*/
|
||||
short lna_gain;
|
||||
|
||||
/*
|
||||
* USB Max frame size (for rt2500usb & rt73usb).
|
||||
*/
|
||||
u16 usb_maxpacket;
|
||||
|
||||
/*
|
||||
* Current TX power value.
|
||||
*/
|
||||
|
@ -111,12 +111,6 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
|
||||
led->led_dev.name = name;
|
||||
led->led_dev.brightness = LED_OFF;
|
||||
|
||||
/*
|
||||
* Ensure the LED is off, it might have been enabled
|
||||
* by the hardware when the device was powered on.
|
||||
*/
|
||||
led->led_dev.brightness_set(&led->led_dev, LED_OFF);
|
||||
|
||||
retval = led_classdev_register(device, &led->led_dev);
|
||||
if (retval) {
|
||||
ERROR(rt2x00dev, "Failed to register led handler.\n");
|
||||
|
@ -132,8 +132,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
ERROR(rt2x00dev,
|
||||
"Attempt to send packet over invalid queue %d.\n"
|
||||
"Please file bug report to %s.\n", qid, DRV_PROJECT);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
goto exit_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -31,6 +31,31 @@
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00pci.h"
|
||||
|
||||
/*
|
||||
* Register access.
|
||||
*/
|
||||
int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
const struct rt2x00_field32 field,
|
||||
u32 *reg)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, offset, reg);
|
||||
if (!rt2x00_get_field32(*reg, field))
|
||||
return 1;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
ERROR(rt2x00dev, "Indirect register access failed: "
|
||||
"offset=0x%.08x, value=0x%.08x\n", offset, *reg);
|
||||
*reg = ~0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
|
||||
|
||||
/*
|
||||
* TX data handlers.
|
||||
*/
|
||||
|
@ -76,6 +76,24 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||
memcpy_toio(rt2x00dev->csr.base + offset, value, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00pci_regbusy_read - Read from register with busy check
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @field: Field to check if register is busy
|
||||
* @reg: Pointer to where register contents should be stored
|
||||
*
|
||||
* This function will read the given register, and checks if the
|
||||
* register is busy. If it is, it will sleep for a couple of
|
||||
* microseconds before reading the register again. If the register
|
||||
* is not read after a certain timeout, this function will return
|
||||
* FALSE.
|
||||
*/
|
||||
int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
const struct rt2x00_field32 field,
|
||||
u32 *reg);
|
||||
|
||||
/**
|
||||
* rt2x00pci_write_tx_data - Initialize data for TX operation
|
||||
* @entry: The entry where the frame is located
|
||||
|
@ -386,7 +386,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
|
||||
u8 rate_idx, rate_flags;
|
||||
|
||||
if (unlikely(rt2x00queue_full(queue)))
|
||||
return -EINVAL;
|
||||
return -ENOBUFS;
|
||||
|
||||
if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
|
||||
ERROR(queue->rt2x00dev,
|
||||
@ -415,7 +415,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
rate_idx = tx_info->control.rates[0].idx;
|
||||
rate_flags = tx_info->control.rates[0].flags;
|
||||
skbdesc = get_skb_frame_desc(entry->skb);
|
||||
skbdesc = get_skb_frame_desc(skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->entry = entry;
|
||||
skbdesc->tx_rate_idx = rate_idx;
|
||||
@ -427,20 +427,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
|
||||
* the frame so we can provide it to the driver seperately.
|
||||
*/
|
||||
if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
|
||||
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
|
||||
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags))
|
||||
rt2x00crypto_tx_remove_iv(skb, iv_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* It could be possible that the queue was corrupted and this
|
||||
* call failed. Just drop the frame, we cannot rollback and pass
|
||||
* the frame to mac80211 because the skb->cb has now been tainted.
|
||||
* call failed. Since we always return NETDEV_TX_OK to mac80211,
|
||||
* this frame will simply be dropped.
|
||||
*/
|
||||
if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
|
||||
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
dev_kfree_skb_any(entry->skb);
|
||||
entry->skb = NULL;
|
||||
return 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
|
||||
|
@ -380,6 +380,8 @@ enum queue_index {
|
||||
* @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
|
||||
* @data_size: Maximum data size for the frames in this queue.
|
||||
* @desc_size: Hardware descriptor size for the data in this queue.
|
||||
* @usb_endpoint: Device endpoint used for communication (USB only)
|
||||
* @usb_maxpacket: Max packet size for given endpoint (USB only)
|
||||
*/
|
||||
struct data_queue {
|
||||
struct rt2x00_dev *rt2x00dev;
|
||||
@ -401,6 +403,9 @@ struct data_queue {
|
||||
|
||||
unsigned short data_size;
|
||||
unsigned short desc_size;
|
||||
|
||||
unsigned short usb_endpoint;
|
||||
unsigned short usb_maxpacket;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -443,6 +448,19 @@ struct data_queue_desc {
|
||||
#define tx_queue_end(__dev) \
|
||||
&(__dev)->tx[(__dev)->ops->tx_queues]
|
||||
|
||||
/**
|
||||
* queue_next - Return pointer to next queue in list (HELPER MACRO).
|
||||
* @__queue: Current queue for which we need the next queue
|
||||
*
|
||||
* Using the current queue address we take the address directly
|
||||
* after the queue to take the next queue. Note that this macro
|
||||
* should be used carefully since it does not protect against
|
||||
* moving past the end of the list. (See macros &queue_end and
|
||||
* &tx_queue_end for determining the end of the queue).
|
||||
*/
|
||||
#define queue_next(__queue) \
|
||||
&(__queue)[1]
|
||||
|
||||
/**
|
||||
* queue_loop - Loop through the queues within a specific range (HELPER MACRO).
|
||||
* @__entry: Pointer where the current queue entry will be stored in.
|
||||
@ -453,8 +471,8 @@ struct data_queue_desc {
|
||||
*/
|
||||
#define queue_loop(__entry, __start, __end) \
|
||||
for ((__entry) = (__start); \
|
||||
prefetch(&(__entry)[1]), (__entry) != (__end); \
|
||||
(__entry) = &(__entry)[1])
|
||||
prefetch(queue_next(__entry)), (__entry) != (__end);\
|
||||
(__entry) = queue_next(__entry))
|
||||
|
||||
/**
|
||||
* queue_for_each - Loop through all queues
|
||||
|
@ -154,6 +154,28 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff);
|
||||
|
||||
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
struct rt2x00_field32 field,
|
||||
u32 *reg)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
|
||||
if (!rt2x00_get_field32(*reg, field))
|
||||
return 1;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
ERROR(rt2x00dev, "Indirect register access failed: "
|
||||
"offset=0x%.08x, value=0x%.08x\n", offset, *reg);
|
||||
*reg = ~0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
|
||||
|
||||
/*
|
||||
* TX data handlers.
|
||||
*/
|
||||
@ -212,10 +234,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry)
|
||||
* length of the data to usb_fill_bulk_urb. Pass the skb
|
||||
* to the driver to determine what the length should be.
|
||||
*/
|
||||
length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb);
|
||||
length = rt2x00dev->ops->lib->get_tx_data_len(entry);
|
||||
|
||||
usb_fill_bulk_urb(entry_priv->urb, usb_dev,
|
||||
usb_sndbulkpipe(usb_dev, 1),
|
||||
usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
|
||||
entry->skb->data, length,
|
||||
rt2x00usb_interrupt_txdone, entry);
|
||||
|
||||
@ -356,10 +378,11 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
|
||||
struct usb_device *usb_dev =
|
||||
to_usb_device_intf(entry->queue->rt2x00dev->dev);
|
||||
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
|
||||
int pipe;
|
||||
|
||||
if (entry->queue->qid == QID_RX) {
|
||||
usb_fill_bulk_urb(entry_priv->urb, usb_dev,
|
||||
usb_rcvbulkpipe(usb_dev, 1),
|
||||
pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
|
||||
usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe,
|
||||
entry->skb->data, entry->skb->len,
|
||||
rt2x00usb_interrupt_rxdone, entry);
|
||||
|
||||
@ -371,6 +394,76 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
|
||||
|
||||
static void rt2x00usb_assign_endpoint(struct data_queue *queue,
|
||||
struct usb_endpoint_descriptor *ep_desc)
|
||||
{
|
||||
struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev);
|
||||
int pipe;
|
||||
|
||||
queue->usb_endpoint = usb_endpoint_num(ep_desc);
|
||||
|
||||
if (queue->qid == QID_RX) {
|
||||
pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint);
|
||||
queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0);
|
||||
} else {
|
||||
pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint);
|
||||
queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1);
|
||||
}
|
||||
|
||||
if (!queue->usb_maxpacket)
|
||||
queue->usb_maxpacket = 1;
|
||||
}
|
||||
|
||||
static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(rt2x00dev->dev);
|
||||
struct usb_host_interface *intf_desc = intf->cur_altsetting;
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
struct data_queue *queue = rt2x00dev->tx;
|
||||
struct usb_endpoint_descriptor *tx_ep_desc = NULL;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Walk through all available endpoints to search for "bulk in"
|
||||
* and "bulk out" endpoints. When we find such endpoints collect
|
||||
* the information we need from the descriptor and assign it
|
||||
* to the queue.
|
||||
*/
|
||||
for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
|
||||
ep_desc = &intf_desc->endpoint[i].desc;
|
||||
|
||||
if (usb_endpoint_is_bulk_in(ep_desc)) {
|
||||
rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
|
||||
} else if (usb_endpoint_is_bulk_out(ep_desc)) {
|
||||
rt2x00usb_assign_endpoint(queue, ep_desc);
|
||||
|
||||
if (queue != queue_end(rt2x00dev))
|
||||
queue = queue_next(queue);
|
||||
tx_ep_desc = ep_desc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* At least 1 endpoint for RX and 1 endpoint for TX must be available.
|
||||
*/
|
||||
if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
|
||||
ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* It might be possible not all queues have a dedicated endpoint.
|
||||
* Loop through all TX queues and copy the endpoint information
|
||||
* which we have gathered from already assigned endpoints.
|
||||
*/
|
||||
txall_queue_for_each(rt2x00dev, queue) {
|
||||
if (!queue->usb_endpoint)
|
||||
rt2x00usb_assign_endpoint(queue, tx_ep_desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue)
|
||||
{
|
||||
@ -441,6 +534,13 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
|
||||
struct data_queue *queue;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Find endpoints for each queue
|
||||
*/
|
||||
status = rt2x00usb_find_endpoints(rt2x00dev);
|
||||
if (status)
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Allocate DMA
|
||||
*/
|
||||
@ -532,11 +632,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
|
||||
rt2x00dev->ops = ops;
|
||||
rt2x00dev->hw = hw;
|
||||
|
||||
rt2x00dev->usb_maxpacket =
|
||||
usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
|
||||
if (!rt2x00dev->usb_maxpacket)
|
||||
rt2x00dev->usb_maxpacket = 1;
|
||||
|
||||
retval = rt2x00usb_alloc_reg(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_device;
|
||||
|
@ -231,6 +231,142 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
|
||||
REGISTER_TIMEOUT16(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_regbusy_read - Read 32bit register word
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @value: Pointer to where register contents should be stored
|
||||
*
|
||||
* This function is a simple wrapper for 32bit register access
|
||||
* through rt2x00usb_vendor_request_buff().
|
||||
*/
|
||||
static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
u32 *value)
|
||||
{
|
||||
__le32 reg;
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
*value = le32_to_cpu(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_register_read_lock - Read 32bit register word
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @value: Pointer to where register contents should be stored
|
||||
*
|
||||
* This function is a simple wrapper for 32bit register access
|
||||
* through rt2x00usb_vendor_req_buff_lock().
|
||||
*/
|
||||
static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
u32 *value)
|
||||
{
|
||||
__le32 reg;
|
||||
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
*value = le32_to_cpu(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_register_multiread - Read 32bit register words
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @value: Pointer to where register contents should be stored
|
||||
* @length: Length of the data
|
||||
*
|
||||
* This function is a simple wrapper for 32bit register access
|
||||
* through rt2x00usb_vendor_request_buff().
|
||||
*/
|
||||
static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
void *value, const u32 length)
|
||||
{
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
value, length,
|
||||
REGISTER_TIMEOUT32(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_register_write - Write 32bit register word
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @value: Data which should be written
|
||||
*
|
||||
* This function is a simple wrapper for 32bit register access
|
||||
* through rt2x00usb_vendor_request_buff().
|
||||
*/
|
||||
static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
u32 value)
|
||||
{
|
||||
__le32 reg = cpu_to_le32(value);
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_register_write_lock - Write 32bit register word
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @value: Data which should be written
|
||||
*
|
||||
* This function is a simple wrapper for 32bit register access
|
||||
* through rt2x00usb_vendor_req_buff_lock().
|
||||
*/
|
||||
static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
u32 value)
|
||||
{
|
||||
__le32 reg = cpu_to_le32(value);
|
||||
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_register_multiwrite - Write 32bit register words
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @value: Data which should be written
|
||||
* @length: Length of the data
|
||||
*
|
||||
* This function is a simple wrapper for 32bit register access
|
||||
* through rt2x00usb_vendor_request_buff().
|
||||
*/
|
||||
static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
void *value, const u32 length)
|
||||
{
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
value, length,
|
||||
REGISTER_TIMEOUT32(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00usb_regbusy_read - Read from register with busy check
|
||||
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||
* @offset: Register offset
|
||||
* @field: Field to check if register is busy
|
||||
* @reg: Pointer to where register contents should be stored
|
||||
*
|
||||
* This function will read the given register, and checks if the
|
||||
* register is busy. If it is, it will sleep for a couple of
|
||||
* microseconds before reading the register again. If the register
|
||||
* is not read after a certain timeout, this function will return
|
||||
* FALSE.
|
||||
*/
|
||||
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
struct rt2x00_field32 field,
|
||||
u32 *reg);
|
||||
|
||||
/*
|
||||
* Radio handlers
|
||||
*/
|
||||
|
@ -55,20 +55,13 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
* the access attempt is considered to have failed,
|
||||
* and we will print an error.
|
||||
*/
|
||||
static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, PHY_CSR3, ®);
|
||||
if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
break;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
#define WAIT_FOR_BBP(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
|
||||
#define WAIT_FOR_RF(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
|
||||
#define WAIT_FOR_MCU(__dev, __reg) \
|
||||
rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \
|
||||
H2M_MAILBOX_CSR_OWNER, (__reg))
|
||||
|
||||
static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u8 value)
|
||||
@ -78,30 +71,20 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
reg = rt61pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
|
||||
|
||||
/*
|
||||
* Write the data into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
|
||||
}
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
|
||||
}
|
||||
|
||||
static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
@ -112,73 +95,54 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the read request into the register.
|
||||
* After the data has been written, we wait until hardware
|
||||
* returns the correct value, if at any time the register
|
||||
* doesn't become available in time, reg will be 0xffffffff
|
||||
* which means we return 0xff to the caller.
|
||||
*/
|
||||
reg = rt61pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
|
||||
|
||||
/*
|
||||
* Write the request into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
*/
|
||||
reg = rt61pci_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
goto exit_fail;
|
||||
WAIT_FOR_BBP(rt2x00dev, ®);
|
||||
}
|
||||
|
||||
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
|
||||
*value = 0xff;
|
||||
}
|
||||
|
||||
static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u32 value)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®);
|
||||
if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
|
||||
goto rf_write;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
/*
|
||||
* Wait until the RF becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
if (WAIT_FOR_RF(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
|
||||
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21);
|
||||
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
|
||||
return;
|
||||
|
||||
rf_write:
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
|
||||
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21);
|
||||
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
}
|
||||
|
||||
@ -196,32 +160,25 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®);
|
||||
/*
|
||||
* Wait until the MCU becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
if (WAIT_FOR_MCU(rt2x00dev, ®)) {
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1);
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1);
|
||||
rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
|
||||
|
||||
if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER))
|
||||
goto exit_fail;
|
||||
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1);
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);
|
||||
rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1);
|
||||
rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®);
|
||||
rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);
|
||||
rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
|
||||
rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®);
|
||||
rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);
|
||||
rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev,
|
||||
"mcu request error. Request 0x%02x failed for token 0x%02x.\n",
|
||||
command, token);
|
||||
}
|
||||
#endif /* CONFIG_RT2X00_LIB_LEDS */
|
||||
|
||||
|
@ -46,7 +46,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
/*
|
||||
* Register access.
|
||||
* All access to the CSR registers will go through the methods
|
||||
* rt73usb_register_read and rt73usb_register_write.
|
||||
* rt2x00usb_register_read and rt2x00usb_register_write.
|
||||
* BBP and RF register require indirect register access,
|
||||
* and use the CSR registers BBPCSR and RFCSR to achieve this.
|
||||
* These indirect registers work with busy bits,
|
||||
@ -57,78 +57,10 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
* and we will print an error.
|
||||
* The _lock versions must be used if you already hold the csr_mutex
|
||||
*/
|
||||
static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 *value)
|
||||
{
|
||||
__le32 reg;
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
®, sizeof(u32), REGISTER_TIMEOUT);
|
||||
*value = le32_to_cpu(reg);
|
||||
}
|
||||
|
||||
static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 *value)
|
||||
{
|
||||
__le32 reg;
|
||||
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
®, sizeof(u32), REGISTER_TIMEOUT);
|
||||
*value = le32_to_cpu(reg);
|
||||
}
|
||||
|
||||
static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
void *value, const u32 length)
|
||||
{
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||
USB_VENDOR_REQUEST_IN, offset,
|
||||
value, length,
|
||||
REGISTER_TIMEOUT32(length));
|
||||
}
|
||||
|
||||
static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 value)
|
||||
{
|
||||
__le32 reg = cpu_to_le32(value);
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
®, sizeof(u32), REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset, u32 value)
|
||||
{
|
||||
__le32 reg = cpu_to_le32(value);
|
||||
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
®, sizeof(u32), REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset,
|
||||
void *value, const u32 length)
|
||||
{
|
||||
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||
USB_VENDOR_REQUEST_OUT, offset,
|
||||
value, length,
|
||||
REGISTER_TIMEOUT32(length));
|
||||
}
|
||||
|
||||
static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, ®);
|
||||
if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
break;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
#define WAIT_FOR_BBP(__dev, __reg) \
|
||||
rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
|
||||
#define WAIT_FOR_RF(__dev, __reg) \
|
||||
rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
|
||||
|
||||
static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u8 value)
|
||||
@ -138,30 +70,20 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
reg = rt73usb_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
|
||||
|
||||
/*
|
||||
* Write the data into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
|
||||
rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
|
||||
}
|
||||
|
||||
rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
|
||||
}
|
||||
|
||||
static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
@ -172,79 +94,59 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
* Wait until the BBP becomes available, afterwards we
|
||||
* can safely write the read request into the register.
|
||||
* After the data has been written, we wait until hardware
|
||||
* returns the correct value, if at any time the register
|
||||
* doesn't become available in time, reg will be 0xffffffff
|
||||
* which means we return 0xff to the caller.
|
||||
*/
|
||||
reg = rt73usb_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
goto exit_fail;
|
||||
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
|
||||
|
||||
/*
|
||||
* Write the request into the BBP.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
|
||||
rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
|
||||
rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
|
||||
rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
|
||||
|
||||
rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
|
||||
|
||||
/*
|
||||
* Wait until the BBP becomes ready.
|
||||
*/
|
||||
reg = rt73usb_bbp_check(rt2x00dev);
|
||||
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
|
||||
goto exit_fail;
|
||||
WAIT_FOR_BBP(rt2x00dev, ®);
|
||||
}
|
||||
|
||||
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
return;
|
||||
|
||||
exit_fail:
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
|
||||
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
|
||||
*value = 0xff;
|
||||
}
|
||||
|
||||
static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u32 value)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
if (!word)
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®);
|
||||
if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
|
||||
goto rf_write;
|
||||
udelay(REGISTER_BUSY_DELAY);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
|
||||
return;
|
||||
|
||||
rf_write:
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
|
||||
|
||||
/*
|
||||
* RF5225 and RF2527 contain 21 bits per RF register value,
|
||||
* all others contain 20 bits.
|
||||
* Wait until the RF becomes available, afterwards we
|
||||
* can safely write the new data into the register.
|
||||
*/
|
||||
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
|
||||
20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527)));
|
||||
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
|
||||
if (WAIT_FOR_RF(rt2x00dev, ®)) {
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
|
||||
/*
|
||||
* RF5225 and RF2527 contain 21 bits per RF register value,
|
||||
* all others contain 20 bits.
|
||||
*/
|
||||
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
|
||||
20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527)));
|
||||
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
|
||||
|
||||
rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
|
||||
rt2x00_rf_write(rt2x00dev, word, value);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||
}
|
||||
@ -253,8 +155,8 @@ rf_write:
|
||||
static const struct rt2x00debug rt73usb_rt2x00debug = {
|
||||
.owner = THIS_MODULE,
|
||||
.csr = {
|
||||
.read = rt73usb_register_read,
|
||||
.write = rt73usb_register_write,
|
||||
.read = rt2x00usb_register_read,
|
||||
.write = rt2x00usb_register_write,
|
||||
.flags = RT2X00DEBUGFS_OFFSET,
|
||||
.word_base = CSR_REG_BASE,
|
||||
.word_size = sizeof(u32),
|
||||
@ -333,10 +235,10 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev,
|
||||
container_of(led_cdev, struct rt2x00_led, led_dev);
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(led->rt2x00dev, MAC_CSR14, ®);
|
||||
rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on);
|
||||
rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off);
|
||||
rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
|
||||
rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -379,7 +281,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||
*/
|
||||
mask = (0xf << crypto->bssidx);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®);
|
||||
reg &= mask;
|
||||
|
||||
if (reg && reg == mask)
|
||||
@ -416,16 +318,16 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||
field.bit_offset = (3 * key->hw_key_idx);
|
||||
field.bit_mask = 0x7 << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR1, ®);
|
||||
rt2x00_set_field32(®, field, crypto->cipher);
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
|
||||
} else {
|
||||
field.bit_offset = (3 * (key->hw_key_idx - 8));
|
||||
field.bit_mask = 0x7 << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR5, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR5, ®);
|
||||
rt2x00_set_field32(®, field, crypto->cipher);
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR5, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -448,12 +350,12 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||
*/
|
||||
mask = 1 << key->hw_key_idx;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®);
|
||||
if (crypto->cmd == SET_KEY)
|
||||
reg |= mask;
|
||||
else if (crypto->cmd == DISABLE_KEY)
|
||||
reg &= ~mask;
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -478,10 +380,10 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
* When both registers are full, we drop the key,
|
||||
* otherwise we use the first invalid entry.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR2, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®);
|
||||
if (reg && reg == ~0) {
|
||||
key->hw_key_idx = 32;
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR3, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®);
|
||||
if (reg && reg == ~0)
|
||||
return -ENOSPC;
|
||||
}
|
||||
@ -509,14 +411,14 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* Send the address and cipher type to the hardware register.
|
||||
* This data fits within the CSR cache size, so we can use
|
||||
* rt73usb_register_multiwrite() directly.
|
||||
* rt2x00usb_register_multiwrite() directly.
|
||||
*/
|
||||
memset(&addr_entry, 0, sizeof(addr_entry));
|
||||
memcpy(&addr_entry, crypto->address, ETH_ALEN);
|
||||
addr_entry.cipher = crypto->cipher;
|
||||
|
||||
reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
|
||||
rt73usb_register_multiwrite(rt2x00dev, reg,
|
||||
rt2x00usb_register_multiwrite(rt2x00dev, reg,
|
||||
&addr_entry, sizeof(addr_entry));
|
||||
|
||||
/*
|
||||
@ -524,9 +426,9 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
* without this received frames will not be decrypted
|
||||
* by the hardware.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR4, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR4, ®);
|
||||
reg |= (1 << crypto->bssidx);
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR4, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
|
||||
|
||||
/*
|
||||
* The driver does not support the IV/EIV generation
|
||||
@ -549,21 +451,21 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
if (key->hw_key_idx < 32) {
|
||||
mask = 1 << key->hw_key_idx;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR2, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®);
|
||||
if (crypto->cmd == SET_KEY)
|
||||
reg |= mask;
|
||||
else if (crypto->cmd == DISABLE_KEY)
|
||||
reg &= ~mask;
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR2, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg);
|
||||
} else {
|
||||
mask = 1 << (key->hw_key_idx - 32);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, SEC_CSR3, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®);
|
||||
if (crypto->cmd == SET_KEY)
|
||||
reg |= mask;
|
||||
else if (crypto->cmd == DISABLE_KEY)
|
||||
reg &= ~mask;
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR3, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -580,7 +482,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
|
||||
* and broadcast frames will always be accepted since
|
||||
* there is no filter for it at this time.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC,
|
||||
!(filter_flags & FIF_FCSFAIL));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL,
|
||||
@ -598,7 +500,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
|
||||
!(filter_flags & FIF_CONTROL));
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
}
|
||||
|
||||
static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||
@ -617,16 +519,16 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||
* bits which (when set to 0) will invalidate the entire beacon.
|
||||
*/
|
||||
beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
|
||||
rt73usb_register_write(rt2x00dev, beacon_base, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
|
||||
|
||||
/*
|
||||
* Enable synchronisation.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
}
|
||||
|
||||
if (flags & CONFIG_UPDATE_MAC) {
|
||||
@ -634,7 +536,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
|
||||
conf->mac[1] = cpu_to_le32(reg);
|
||||
|
||||
rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
|
||||
rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2,
|
||||
conf->mac, sizeof(conf->mac));
|
||||
}
|
||||
|
||||
@ -643,7 +545,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3);
|
||||
conf->bssid[1] = cpu_to_le32(reg);
|
||||
|
||||
rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
|
||||
rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4,
|
||||
conf->bssid, sizeof(conf->bssid));
|
||||
}
|
||||
}
|
||||
@ -653,26 +555,26 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,
|
||||
!!erp->short_preamble);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
|
||||
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR8, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs);
|
||||
rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
|
||||
rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR8, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
|
||||
}
|
||||
|
||||
static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
|
||||
@ -818,14 +720,14 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
|
||||
rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, PHY_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, PHY_CSR0, ®);
|
||||
|
||||
rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
|
||||
(rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
|
||||
rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
|
||||
(rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
|
||||
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5225))
|
||||
@ -915,12 +817,12 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT,
|
||||
libconf->conf->long_frame_max_tx_count);
|
||||
rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT,
|
||||
libconf->conf->short_frame_max_tx_count);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
|
||||
}
|
||||
|
||||
static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
|
||||
@ -928,18 +830,18 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL,
|
||||
libconf->conf->beacon_int * 16);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
}
|
||||
|
||||
static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
|
||||
@ -972,13 +874,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* Update FCS error count from register.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, STA_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®);
|
||||
qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
|
||||
|
||||
/*
|
||||
* Update False CCA count from register.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, STA_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®);
|
||||
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
|
||||
}
|
||||
|
||||
@ -1138,7 +1040,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
|
||||
* Wait for stable hardware.
|
||||
*/
|
||||
for (i = 0; i < 100; i++) {
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
if (reg)
|
||||
break;
|
||||
msleep(1);
|
||||
@ -1180,13 +1082,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
|
||||
rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
|
||||
@ -1195,12 +1097,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
|
||||
rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg);
|
||||
|
||||
/*
|
||||
* CCK TXD BBP registers
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR2, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13);
|
||||
rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12);
|
||||
@ -1209,77 +1111,77 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10);
|
||||
rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR2, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg);
|
||||
|
||||
/*
|
||||
* OFDM TXD BBP registers
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR3, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7);
|
||||
rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6);
|
||||
rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5);
|
||||
rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR3, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR7, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59);
|
||||
rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53);
|
||||
rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49);
|
||||
rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR7, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR8, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44);
|
||||
rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42);
|
||||
rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42);
|
||||
rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR6, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR6, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR6, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
|
||||
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
|
||||
|
||||
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
|
||||
return -EBUSY;
|
||||
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
|
||||
|
||||
/*
|
||||
* Invalidate all Shared Keys (SEC_CSR0),
|
||||
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
|
||||
*/
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
|
||||
rt73usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
|
||||
|
||||
reg = 0x000023b0;
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527))
|
||||
rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1);
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
|
||||
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
|
||||
/*
|
||||
* Clear all beacons
|
||||
@ -1287,36 +1189,36 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
* the first byte since that byte contains the VALID and OWNER
|
||||
* bits which (when set to 0) will invalidate the entire beacon.
|
||||
*/
|
||||
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
|
||||
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
|
||||
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
|
||||
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
|
||||
|
||||
/*
|
||||
* We must clear the error counters.
|
||||
* These registers are cleared on read,
|
||||
* so we may pass a useless variable to store the value.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, STA_CSR0, ®);
|
||||
rt73usb_register_read(rt2x00dev, STA_CSR1, ®);
|
||||
rt73usb_register_read(rt2x00dev, STA_CSR2, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, STA_CSR2, ®);
|
||||
|
||||
/*
|
||||
* Reset MAC and BBP registers.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1);
|
||||
rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0);
|
||||
rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1394,11 +1296,11 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX,
|
||||
(state == STATE_RADIO_RX_OFF) ||
|
||||
(state == STATE_RADIO_RX_OFF_LINK));
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
}
|
||||
|
||||
static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
@ -1415,12 +1317,12 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
|
||||
|
||||
/*
|
||||
* Disable synchronisation.
|
||||
*/
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0);
|
||||
|
||||
rt2x00usb_disable_radio(rt2x00dev);
|
||||
}
|
||||
@ -1433,10 +1335,10 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
|
||||
|
||||
put_to_sleep = (state != STATE_AWAKE);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR12, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
|
||||
rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR12, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
|
||||
|
||||
/*
|
||||
* Device is not guaranteed to be in the requested state yet.
|
||||
@ -1444,7 +1346,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
|
||||
* device has entered the correct state.
|
||||
*/
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR12, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®);
|
||||
state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
|
||||
if (state == !put_to_sleep)
|
||||
return 0;
|
||||
@ -1584,11 +1486,11 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
|
||||
* Disable beaconing while we are reloading the beacon data,
|
||||
* otherwise we might be sending out invalid data.
|
||||
*/
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
|
||||
/*
|
||||
* Write entire beacon with descriptor to register.
|
||||
@ -1606,8 +1508,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
|
||||
entry->skb = NULL;
|
||||
}
|
||||
|
||||
static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
|
||||
struct sk_buff *skb)
|
||||
static int rt73usb_get_tx_data_len(struct queue_entry *entry)
|
||||
{
|
||||
int length;
|
||||
|
||||
@ -1615,8 +1516,8 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
|
||||
* The length _must_ be a multiple of 4,
|
||||
* but it must _not_ be a multiple of the USB packet size.
|
||||
*/
|
||||
length = roundup(skb->len, 4);
|
||||
length += (4 * !(length % rt2x00dev->usb_maxpacket));
|
||||
length = roundup(entry->skb->len, 4);
|
||||
length += (4 * !(length % entry->queue->usb_maxpacket));
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -1635,14 +1536,14 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
|
||||
* For Wi-Fi faily generated beacons between participating stations.
|
||||
* Set TBTT phase adaptive adjustment step to 8us (default 16us)
|
||||
*/
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®);
|
||||
if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1881,7 +1782,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
* Identify RF chipset.
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
|
||||
|
||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) {
|
||||
@ -2235,33 +2136,33 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
field.bit_offset = queue_idx * 16;
|
||||
field.bit_mask = 0xffff << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®);
|
||||
rt2x00_set_field32(®, field, queue->txop);
|
||||
rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
|
||||
} else if (queue_idx < 4) {
|
||||
field.bit_offset = (queue_idx - 2) * 16;
|
||||
field.bit_mask = 0xffff << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®);
|
||||
rt2x00_set_field32(®, field, queue->txop);
|
||||
rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
|
||||
}
|
||||
|
||||
/* Update WMM registers */
|
||||
field.bit_offset = queue_idx * 4;
|
||||
field.bit_mask = 0xf << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AIFSN_CSR, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->aifs);
|
||||
rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, CWMIN_CSR, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->cw_min);
|
||||
rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, CWMAX_CSR, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->cw_max);
|
||||
rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg);
|
||||
rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2279,9 +2180,9 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
|
||||
u64 tsf;
|
||||
u32 reg;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR13, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, ®);
|
||||
tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR12, ®);
|
||||
rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, ®);
|
||||
tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
|
||||
|
||||
return tsf;
|
||||
|
@ -111,6 +111,13 @@ struct rtl8187_priv {
|
||||
u8 signal;
|
||||
u8 quality;
|
||||
u8 noise;
|
||||
u8 slot_time;
|
||||
u8 aifsn[4];
|
||||
struct {
|
||||
__le64 buf;
|
||||
struct urb *urb;
|
||||
struct sk_buff_head queue;
|
||||
} b_tx_status;
|
||||
};
|
||||
|
||||
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
|
||||
|
@ -176,8 +176,27 @@ static void rtl8187_tx_cb(struct urb *urb)
|
||||
skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
|
||||
sizeof(struct rtl8187_tx_hdr));
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
|
||||
if (!urb->status &&
|
||||
!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
|
||||
priv->is_rtl8187b) {
|
||||
skb_queue_tail(&priv->b_tx_status.queue, skb);
|
||||
|
||||
/* queue is "full", discard last items */
|
||||
while (skb_queue_len(&priv->b_tx_status.queue) > 5) {
|
||||
struct sk_buff *old_skb;
|
||||
|
||||
dev_dbg(&priv->udev->dev,
|
||||
"transmit status queue full\n");
|
||||
|
||||
old_skb = skb_dequeue(&priv->b_tx_status.queue);
|
||||
ieee80211_tx_status_irqsafe(hw, old_skb);
|
||||
}
|
||||
} else {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status)
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
}
|
||||
}
|
||||
|
||||
static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
@ -219,7 +238,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
hdr->flags = cpu_to_le32(flags);
|
||||
hdr->len = 0;
|
||||
hdr->rts_duration = rts_dur;
|
||||
hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
|
||||
hdr->retry = cpu_to_le32(info->control.rates[0].count << 8);
|
||||
buf = hdr;
|
||||
|
||||
ep = 2;
|
||||
@ -237,7 +256,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
hdr->flags = cpu_to_le32(flags);
|
||||
hdr->rts_duration = rts_dur;
|
||||
hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
|
||||
hdr->retry = cpu_to_le32(info->control.rates[0].count << 8);
|
||||
hdr->tx_duration =
|
||||
ieee80211_generic_frame_duration(dev, priv->vif,
|
||||
skb->len, txrate);
|
||||
@ -403,6 +422,109 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl8187b_status_cb(struct urb *urb)
|
||||
{
|
||||
struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context;
|
||||
struct rtl8187_priv *priv = hw->priv;
|
||||
u64 val;
|
||||
unsigned int cmd_type;
|
||||
|
||||
if (unlikely(urb->status)) {
|
||||
usb_free_urb(urb);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from status buffer:
|
||||
*
|
||||
* bits [30:31] = cmd type:
|
||||
* - 0 indicates tx beacon interrupt
|
||||
* - 1 indicates tx close descriptor
|
||||
*
|
||||
* In the case of tx beacon interrupt:
|
||||
* [0:9] = Last Beacon CW
|
||||
* [10:29] = reserved
|
||||
* [30:31] = 00b
|
||||
* [32:63] = Last Beacon TSF
|
||||
*
|
||||
* If it's tx close descriptor:
|
||||
* [0:7] = Packet Retry Count
|
||||
* [8:14] = RTS Retry Count
|
||||
* [15] = TOK
|
||||
* [16:27] = Sequence No
|
||||
* [28] = LS
|
||||
* [29] = FS
|
||||
* [30:31] = 01b
|
||||
* [32:47] = unused (reserved?)
|
||||
* [48:63] = MAC Used Time
|
||||
*/
|
||||
val = le64_to_cpu(priv->b_tx_status.buf);
|
||||
|
||||
cmd_type = (val >> 30) & 0x3;
|
||||
if (cmd_type == 1) {
|
||||
unsigned int pkt_rc, seq_no;
|
||||
bool tok;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_hdr *ieee80211hdr;
|
||||
unsigned long flags;
|
||||
|
||||
pkt_rc = val & 0xFF;
|
||||
tok = val & (1 << 15);
|
||||
seq_no = (val >> 16) & 0xFFF;
|
||||
|
||||
spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags);
|
||||
skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) {
|
||||
ieee80211hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
/*
|
||||
* While testing, it was discovered that the seq_no
|
||||
* doesn't actually contains the sequence number.
|
||||
* Instead of returning just the 12 bits of sequence
|
||||
* number, hardware is returning entire sequence control
|
||||
* (fragment number plus sequence number) in a 12 bit
|
||||
* only field overflowing after some time. As a
|
||||
* workaround, just consider the lower bits, and expect
|
||||
* it's unlikely we wrongly ack some sent data
|
||||
*/
|
||||
if ((le16_to_cpu(ieee80211hdr->seq_ctrl)
|
||||
& 0xFFF) == seq_no)
|
||||
break;
|
||||
}
|
||||
if (skb != (struct sk_buff *) &priv->b_tx_status.queue) {
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
__skb_unlink(skb, &priv->b_tx_status.queue);
|
||||
if (tok)
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.rates[0].count = pkt_rc + 1;
|
||||
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
|
||||
}
|
||||
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
struct urb *entry;
|
||||
|
||||
entry = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
priv->b_tx_status.urb = entry;
|
||||
|
||||
usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
|
||||
&priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
|
||||
rtl8187b_status_cb, dev);
|
||||
|
||||
usb_submit_urb(entry, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
@ -712,6 +834,13 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
|
||||
|
||||
rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1);
|
||||
|
||||
priv->slot_time = 0x9;
|
||||
priv->aifsn[0] = 2; /* AIFSN[AC_VO] */
|
||||
priv->aifsn[1] = 2; /* AIFSN[AC_VI] */
|
||||
priv->aifsn[2] = 7; /* AIFSN[AC_BK] */
|
||||
priv->aifsn[3] = 3; /* AIFSN[AC_BE] */
|
||||
rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -748,6 +877,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
||||
(7 << 0 /* long retry limit */) |
|
||||
(7 << 21 /* MAX TX DMA */));
|
||||
rtl8187_init_urbs(dev);
|
||||
rtl8187b_init_status_urb(dev);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
}
|
||||
@ -824,6 +954,9 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
|
||||
usb_kill_urb(info->urb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
|
||||
dev_kfree_skb_any(skb);
|
||||
usb_kill_urb(priv->b_tx_status.urb);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
|
||||
@ -919,24 +1052,38 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for
|
||||
* example. Thus we have to use raw values for AC_*_PARAM register addresses.
|
||||
*/
|
||||
static __le32 *rtl8187b_ac_addr[4] = {
|
||||
(__le32 *) 0xFFF0, /* AC_VO */
|
||||
(__le32 *) 0xFFF4, /* AC_VI */
|
||||
(__le32 *) 0xFFFC, /* AC_BK */
|
||||
(__le32 *) 0xFFF8, /* AC_BE */
|
||||
};
|
||||
|
||||
#define SIFS_TIME 0xa
|
||||
|
||||
static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot,
|
||||
bool use_short_preamble)
|
||||
{
|
||||
if (priv->is_rtl8187b) {
|
||||
u8 difs, eifs, slot_time;
|
||||
u8 difs, eifs;
|
||||
u16 ack_timeout;
|
||||
int queue;
|
||||
|
||||
if (use_short_slot) {
|
||||
slot_time = 0x9;
|
||||
priv->slot_time = 0x9;
|
||||
difs = 0x1c;
|
||||
eifs = 0x53;
|
||||
} else {
|
||||
slot_time = 0x14;
|
||||
priv->slot_time = 0x14;
|
||||
difs = 0x32;
|
||||
eifs = 0x5b;
|
||||
}
|
||||
rtl818x_iowrite8(priv, &priv->map->SIFS, 0xa);
|
||||
rtl818x_iowrite8(priv, &priv->map->SLOT, slot_time);
|
||||
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
|
||||
rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time);
|
||||
rtl818x_iowrite8(priv, &priv->map->DIFS, difs);
|
||||
|
||||
/*
|
||||
@ -957,18 +1104,21 @@ static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot,
|
||||
ack_timeout += 144;
|
||||
rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER,
|
||||
DIV_ROUND_UP(ack_timeout, 4));
|
||||
|
||||
for (queue = 0; queue < 4; queue++)
|
||||
rtl818x_iowrite8(priv, (u8 *) rtl8187b_ac_addr[queue],
|
||||
priv->aifsn[queue] * priv->slot_time +
|
||||
SIFS_TIME);
|
||||
} else {
|
||||
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
|
||||
if (use_short_slot) {
|
||||
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
|
||||
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
|
||||
rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
|
||||
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
|
||||
} else {
|
||||
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
|
||||
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
|
||||
rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
|
||||
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1017,6 +1167,42 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
|
||||
rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
|
||||
}
|
||||
|
||||
static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
u8 cw_min, cw_max;
|
||||
|
||||
if (queue > 3)
|
||||
return -EINVAL;
|
||||
|
||||
cw_min = fls(params->cw_min);
|
||||
cw_max = fls(params->cw_max);
|
||||
|
||||
if (priv->is_rtl8187b) {
|
||||
priv->aifsn[queue] = params->aifs;
|
||||
|
||||
/*
|
||||
* This is the structure of AC_*_PARAM registers in 8187B:
|
||||
* - TXOP limit field, bit offset = 16
|
||||
* - ECWmax, bit offset = 12
|
||||
* - ECWmin, bit offset = 8
|
||||
* - AIFS, bit offset = 0
|
||||
*/
|
||||
rtl818x_iowrite32(priv, rtl8187b_ac_addr[queue],
|
||||
(params->txop << 16) | (cw_max << 12) |
|
||||
(cw_min << 8) | (params->aifs *
|
||||
priv->slot_time + SIFS_TIME));
|
||||
} else {
|
||||
if (queue != 0)
|
||||
return -EINVAL;
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->CW_VAL,
|
||||
cw_min | (cw_max << 4));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops rtl8187_ops = {
|
||||
.tx = rtl8187_tx,
|
||||
.start = rtl8187_start,
|
||||
@ -1027,6 +1213,7 @@ static const struct ieee80211_ops rtl8187_ops = {
|
||||
.config_interface = rtl8187_config_interface,
|
||||
.bss_info_changed = rtl8187_bss_info_changed,
|
||||
.configure_filter = rtl8187_configure_filter,
|
||||
.conf_tx = rtl8187_conf_tx
|
||||
};
|
||||
|
||||
static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
|
||||
@ -1222,9 +1409,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
||||
}
|
||||
|
||||
if (priv->is_rtl8187b) {
|
||||
printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
|
||||
"is EXPERIMENTAL, and could damage your\n"
|
||||
" hardware, use at your own risk\n");
|
||||
printk(KERN_WARNING "rtl8187: 8187B chip detected.\n");
|
||||
dev->flags |= IEEE80211_HW_SIGNAL_DBM;
|
||||
} else {
|
||||
dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
|
||||
@ -1256,6 +1441,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
||||
goto err_free_dev;
|
||||
}
|
||||
mutex_init(&priv->conf_mutex);
|
||||
skb_queue_head_init(&priv->b_tx_status.queue);
|
||||
|
||||
printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
|
||||
wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
|
||||
|
@ -878,12 +878,6 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
|
||||
for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
|
||||
rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
|
||||
|
||||
rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28);
|
||||
rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28);
|
||||
rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28);
|
||||
rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28);
|
||||
rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
|
||||
|
||||
rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
|
||||
rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
|
||||
rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
|
||||
|
@ -1042,6 +1042,68 @@ enum ieee80211_spectrum_mgmt_actioncode {
|
||||
WLAN_ACTION_SPCT_CHL_SWITCH = 4,
|
||||
};
|
||||
|
||||
/*
|
||||
* IEEE 802.11-2007 7.3.2.9 Country information element
|
||||
*
|
||||
* Minimum length is 8 octets, ie len must be evenly
|
||||
* divisible by 2
|
||||
*/
|
||||
|
||||
/* Although the spec says 8 I'm seeing 6 in practice */
|
||||
#define IEEE80211_COUNTRY_IE_MIN_LEN 6
|
||||
|
||||
/*
|
||||
* For regulatory extension stuff see IEEE 802.11-2007
|
||||
* Annex I (page 1141) and Annex J (page 1147). Also
|
||||
* review 7.3.2.9.
|
||||
*
|
||||
* When dot11RegulatoryClassesRequired is true and the
|
||||
* first_channel/reg_extension_id is >= 201 then the IE
|
||||
* compromises of the 'ext' struct represented below:
|
||||
*
|
||||
* - Regulatory extension ID - when generating IE this just needs
|
||||
* to be monotonically increasing for each triplet passed in
|
||||
* the IE
|
||||
* - Regulatory class - index into set of rules
|
||||
* - Coverage class - index into air propagation time (Table 7-27),
|
||||
* in microseconds, you can compute the air propagation time from
|
||||
* the index by multiplying by 3, so index 10 yields a propagation
|
||||
* of 10 us. Valid values are 0-31, values 32-255 are not defined
|
||||
* yet. A value of 0 inicates air propagation of <= 1 us.
|
||||
*
|
||||
* See also Table I.2 for Emission limit sets and table
|
||||
* I.3 for Behavior limit sets. Table J.1 indicates how to map
|
||||
* a reg_class to an emission limit set and behavior limit set.
|
||||
*/
|
||||
#define IEEE80211_COUNTRY_EXTENSION_ID 201
|
||||
|
||||
/*
|
||||
* Channels numbers in the IE must be monotonically increasing
|
||||
* if dot11RegulatoryClassesRequired is not true.
|
||||
*
|
||||
* If dot11RegulatoryClassesRequired is true consecutive
|
||||
* subband triplets following a regulatory triplet shall
|
||||
* have monotonically increasing first_channel number fields.
|
||||
*
|
||||
* Channel numbers shall not overlap.
|
||||
*
|
||||
* Note that max_power is signed.
|
||||
*/
|
||||
struct ieee80211_country_ie_triplet {
|
||||
union {
|
||||
struct {
|
||||
u8 first_channel;
|
||||
u8 num_channels;
|
||||
s8 max_power;
|
||||
} __attribute__ ((packed)) chans;
|
||||
struct {
|
||||
u8 reg_extension_id;
|
||||
u8 reg_class;
|
||||
u8 coverage_class;
|
||||
} __attribute__ ((packed)) ext;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BACK action code */
|
||||
enum ieee80211_back_actioncode {
|
||||
WLAN_ACTION_ADDBA_REQ = 0,
|
||||
|
@ -508,6 +508,8 @@ enum nl80211_band_attr {
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
|
||||
* on this channel in current regulatory domain.
|
||||
* @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
|
||||
* (100 * dBm).
|
||||
*/
|
||||
enum nl80211_frequency_attr {
|
||||
__NL80211_FREQUENCY_ATTR_INVALID,
|
||||
@ -516,12 +518,15 @@ enum nl80211_frequency_attr {
|
||||
NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
|
||||
NL80211_FREQUENCY_ATTR_NO_IBSS,
|
||||
NL80211_FREQUENCY_ATTR_RADAR,
|
||||
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
|
||||
NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
|
||||
|
||||
/**
|
||||
* enum nl80211_bitrate_attr - bitrate attributes
|
||||
* @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
|
||||
|
@ -108,6 +108,7 @@ struct rfkill {
|
||||
|
||||
struct device dev;
|
||||
struct list_head node;
|
||||
enum rfkill_state state_for_resume;
|
||||
};
|
||||
#define to_rfkill(d) container_of(d, struct rfkill, dev)
|
||||
|
||||
|
@ -181,6 +181,11 @@ struct ieee80211_supported_band {
|
||||
* struct wiphy - wireless hardware description
|
||||
* @idx: the wiphy index assigned to this item
|
||||
* @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
|
||||
* @fw_handles_regulatory: tells us the firmware for this device
|
||||
* has its own regulatory solution and cannot identify the
|
||||
* ISO / IEC 3166 alpha2 it belongs to. When this is enabled
|
||||
* we will disregard the first regulatory hint (when the
|
||||
* initiator is %REGDOM_SET_BY_CORE).
|
||||
* @reg_notifier: the driver's regulatory notification callback
|
||||
*/
|
||||
struct wiphy {
|
||||
@ -192,6 +197,8 @@ struct wiphy {
|
||||
/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
|
||||
u16 interface_modes;
|
||||
|
||||
bool fw_handles_regulatory;
|
||||
|
||||
/* If multiple wiphys are registered and you're handed e.g.
|
||||
* a regular netdev with assigned ieee80211_ptr, you won't
|
||||
* know whether it points to a wiphy your driver has registered
|
||||
@ -373,4 +380,19 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
|
||||
* for a regulatory domain structure for the respective country.
|
||||
*/
|
||||
extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2);
|
||||
|
||||
/**
|
||||
* regulatory_hint_11d - hints a country IE as a regulatory domain
|
||||
* @wiphy: the wireless device giving the hint (used only for reporting
|
||||
* conflicts)
|
||||
* @country_ie: pointer to the country IE
|
||||
* @country_ie_len: length of the country IE
|
||||
*
|
||||
* We will intersect the rd with the what CRDA tells us should apply
|
||||
* for the alpha2 this country IE belongs to, this prevents APs from
|
||||
* sending us incorrect or outdated information against a country.
|
||||
*/
|
||||
extern void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len);
|
||||
#endif /* __NET_WIRELESS_H */
|
||||
|
@ -16,20 +16,20 @@ menu "Rate control algorithm selection"
|
||||
|
||||
config MAC80211_RC_PID
|
||||
bool "PID controller based rate control algorithm" if EMBEDDED
|
||||
default y
|
||||
---help---
|
||||
This option enables a TX rate control algorithm for
|
||||
mac80211 that uses a PID controller to select the TX
|
||||
rate.
|
||||
|
||||
config MAC80211_RC_MINSTREL
|
||||
bool "Minstrel"
|
||||
bool "Minstrel" if EMBEDDED
|
||||
default y
|
||||
---help---
|
||||
This option enables the 'minstrel' TX rate control algorithm
|
||||
|
||||
choice
|
||||
prompt "Default rate control algorithm"
|
||||
default MAC80211_RC_DEFAULT_PID
|
||||
default MAC80211_RC_DEFAULT_MINSTREL
|
||||
---help---
|
||||
This option selects the default rate control algorithm
|
||||
mac80211 will use. Note that this default can still be
|
||||
@ -55,8 +55,8 @@ endchoice
|
||||
|
||||
config MAC80211_RC_DEFAULT
|
||||
string
|
||||
default "pid" if MAC80211_RC_DEFAULT_PID
|
||||
default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
|
||||
default "pid" if MAC80211_RC_DEFAULT_PID
|
||||
default ""
|
||||
|
||||
endmenu
|
||||
|
@ -36,7 +36,7 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
|
||||
|
||||
ht_cap->ht_supported = true;
|
||||
|
||||
ht_cap->cap = ht_cap->cap & sband->ht_cap.cap;
|
||||
ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & sband->ht_cap.cap;
|
||||
ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS;
|
||||
ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
|
||||
|
||||
|
@ -722,7 +722,6 @@ EXPORT_SYMBOL(ieee80211_alloc_hw);
|
||||
int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
const char *name;
|
||||
int result;
|
||||
enum ieee80211_band band;
|
||||
struct net_device *mdev;
|
||||
@ -787,8 +786,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
mdev->header_ops = &ieee80211_header_ops;
|
||||
mdev->set_multicast_list = ieee80211_master_set_multicast_list;
|
||||
|
||||
name = wiphy_dev(local->hw.wiphy)->driver->name;
|
||||
local->hw.workqueue = create_freezeable_workqueue(name);
|
||||
local->hw.workqueue =
|
||||
create_freezeable_workqueue(wiphy_name(local->hw.wiphy));
|
||||
if (!local->hw.workqueue) {
|
||||
result = -ENOMEM;
|
||||
goto fail_workqueue;
|
||||
|
@ -802,6 +802,10 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
|
||||
mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* The disassoc 'reason' argument can be either our own reason
|
||||
* if self disconnected or a reason code from the AP.
|
||||
*/
|
||||
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_if_sta *ifsta, bool deauth,
|
||||
bool self_disconnected, u16 reason)
|
||||
@ -848,7 +852,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
ieee80211_sta_send_apinfo(sdata, ifsta);
|
||||
|
||||
if (self_disconnected)
|
||||
if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT)
|
||||
ifsta->state = IEEE80211_STA_MLME_DISABLED;
|
||||
|
||||
sta_info_unlink(&sta);
|
||||
@ -1163,7 +1167,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
IEEE80211_RETRY_AUTH_INTERVAL);
|
||||
}
|
||||
|
||||
ieee80211_set_disassoc(sdata, ifsta, false, false, 0);
|
||||
ieee80211_set_disassoc(sdata, ifsta, false, false, reason_code);
|
||||
}
|
||||
|
||||
|
||||
@ -1736,6 +1740,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
ap_ht_cap_flags);
|
||||
}
|
||||
|
||||
if (elems.country_elem) {
|
||||
/* Note we are only reviewing this on beacons
|
||||
* for the BSSID we are associated to */
|
||||
regulatory_hint_11d(local->hw.wiphy,
|
||||
elems.country_elem, elems.country_elem_len);
|
||||
}
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba
|
||||
if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
|
||||
spinfo->tx_num_failed += 2;
|
||||
spinfo->tx_num_xmit++;
|
||||
} else if (info->status.rates[0].count) {
|
||||
} else if (info->status.rates[0].count > 1) {
|
||||
spinfo->tx_num_failed++;
|
||||
spinfo->tx_num_xmit++;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
@ -125,10 +126,10 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
|
||||
{
|
||||
struct blkcipher_desc desc = { .tfm = tfm };
|
||||
struct scatterlist sg;
|
||||
__le32 *icv;
|
||||
__le32 icv;
|
||||
|
||||
icv = (__le32 *)(data + data_len);
|
||||
*icv = cpu_to_le32(~crc32_le(~0, data, data_len));
|
||||
icv = cpu_to_le32(~crc32_le(~0, data, data_len));
|
||||
put_unaligned(icv, (__le32 *)(data + data_len));
|
||||
|
||||
crypto_blkcipher_setkey(tfm, rc4key, klen);
|
||||
sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
|
||||
|
@ -565,22 +565,37 @@ static void rfkill_release(struct device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int rfkill_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
/* mark class device as suspended */
|
||||
if (dev->power.power_state.event != state.event)
|
||||
dev->power.power_state = state;
|
||||
|
||||
/* store state for the resume handler */
|
||||
rfkill->state_for_resume = rfkill->state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfkill_resume(struct device *dev)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
enum rfkill_state newstate;
|
||||
|
||||
if (dev->power.power_state.event != PM_EVENT_ON) {
|
||||
mutex_lock(&rfkill->mutex);
|
||||
|
||||
dev->power.power_state.event = PM_EVENT_ON;
|
||||
|
||||
/*
|
||||
* rfkill->state could have been modified before we got
|
||||
* called, and won't be updated by rfkill_toggle_radio()
|
||||
* in force mode. Sync it FIRST.
|
||||
*/
|
||||
if (rfkill->get_state &&
|
||||
!rfkill->get_state(rfkill->data, &newstate))
|
||||
rfkill->state = newstate;
|
||||
|
||||
/*
|
||||
* If we are under EPO, kick transmitter offline,
|
||||
* otherwise restore to pre-suspend state.
|
||||
@ -590,7 +605,7 @@ static int rfkill_resume(struct device *dev)
|
||||
rfkill_toggle_radio(rfkill,
|
||||
rfkill_epo_lock_active ?
|
||||
RFKILL_STATE_SOFT_BLOCKED :
|
||||
rfkill->state,
|
||||
rfkill->state_for_resume,
|
||||
1);
|
||||
|
||||
mutex_unlock(&rfkill->mutex);
|
||||
|
@ -1,6 +1,15 @@
|
||||
config CFG80211
|
||||
tristate "Improved wireless configuration API"
|
||||
|
||||
config CFG80211_REG_DEBUG
|
||||
bool "cfg80211 regulatory debugging"
|
||||
depends on CFG80211
|
||||
default n
|
||||
---help---
|
||||
You can enable this if you want to debug regulatory changes.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config NL80211
|
||||
bool "nl80211 new netlink interface support"
|
||||
depends on CFG80211
|
||||
@ -40,6 +49,8 @@ config WIRELESS_OLD_REGULATORY
|
||||
ieee80211_regdom module parameter. This is being phased out and you
|
||||
should stop using them ASAP.
|
||||
|
||||
Note: You will need CRDA if you want 802.11d support
|
||||
|
||||
Say Y unless you have installed a new userspace application.
|
||||
Also say Y if have one currently depending on the ieee80211_regdom
|
||||
module parameter and cannot port it to use the new userspace
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "nl80211.h"
|
||||
#include "core.h"
|
||||
#include "sysfs.h"
|
||||
#include "reg.h"
|
||||
|
||||
/* name for sysfs, %d is appended */
|
||||
#define PHY_NAME "phy"
|
||||
@ -348,6 +347,10 @@ void wiphy_unregister(struct wiphy *wiphy)
|
||||
/* unlock again before freeing */
|
||||
mutex_unlock(&drv->mtx);
|
||||
|
||||
/* If this device got a regulatory hint tell core its
|
||||
* free to listen now to a new shiny device regulatory hint */
|
||||
reg_device_remove(wiphy);
|
||||
|
||||
list_del(&drv->list);
|
||||
device_del(&drv->wiphy.dev);
|
||||
debugfs_remove(drv->wiphy.debugfsdir);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <net/genetlink.h>
|
||||
#include <net/wireless.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "reg.h"
|
||||
|
||||
struct cfg80211_registered_device {
|
||||
struct cfg80211_ops *ops;
|
||||
@ -21,6 +22,18 @@ struct cfg80211_registered_device {
|
||||
* any call is in progress */
|
||||
struct mutex mtx;
|
||||
|
||||
/* ISO / IEC 3166 alpha2 for which this device is receiving
|
||||
* country IEs on, this can help disregard country IEs from APs
|
||||
* on the same alpha2 quickly. The alpha2 may differ from
|
||||
* cfg80211_regdomain's alpha2 when an intersection has occurred.
|
||||
* If the AP is reconfigured this can also be used to tell us if
|
||||
* the country on the country IE changed. */
|
||||
char country_ie_alpha2[2];
|
||||
|
||||
/* If a Country IE has been received this tells us the environment
|
||||
* which its telling us its in. This defaults to ENVIRON_ANY */
|
||||
enum environment_cap env;
|
||||
|
||||
/* wiphy index, internal only */
|
||||
int idx;
|
||||
|
||||
|
@ -198,6 +198,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||
if (chan->flags & IEEE80211_CHAN_RADAR)
|
||||
NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
|
||||
|
||||
NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
||||
DBM_TO_MBM(chan->max_power));
|
||||
|
||||
nla_nest_end(msg, nl_freq);
|
||||
}
|
||||
|
||||
@ -1760,7 +1763,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
mutex_lock(&cfg80211_drv_mutex);
|
||||
r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data);
|
||||
r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY);
|
||||
mutex_unlock(&cfg80211_drv_mutex);
|
||||
return r;
|
||||
}
|
||||
|
@ -60,12 +60,18 @@
|
||||
* @intersect: indicates whether the wireless core should intersect
|
||||
* the requested regulatory domain with the presently set regulatory
|
||||
* domain.
|
||||
* @country_ie_checksum: checksum of the last processed and accepted
|
||||
* country IE
|
||||
* @country_ie_env: lets us know if the AP is telling us we are outdoor,
|
||||
* indoor, or if it doesn't matter
|
||||
*/
|
||||
struct regulatory_request {
|
||||
struct wiphy *wiphy;
|
||||
enum reg_set_by initiator;
|
||||
char alpha2[2];
|
||||
bool intersect;
|
||||
u32 country_ie_checksum;
|
||||
enum environment_cap country_ie_env;
|
||||
};
|
||||
|
||||
/* Receipt of information from last regulatory request */
|
||||
@ -85,6 +91,11 @@ static u32 supported_bandwidths[] = {
|
||||
* information to give us an alpha2 */
|
||||
static const struct ieee80211_regdomain *cfg80211_regdomain;
|
||||
|
||||
/* We use this as a place for the rd structure built from the
|
||||
* last parsed country IE to rest until CRDA gets back to us with
|
||||
* what it thinks should apply for the same country */
|
||||
static const struct ieee80211_regdomain *country_ie_regdomain;
|
||||
|
||||
/* We keep a static world regulatory domain in case of the absence of CRDA */
|
||||
static const struct ieee80211_regdomain world_regdom = {
|
||||
.n_reg_rules = 1,
|
||||
@ -264,6 +275,18 @@ static bool is_unknown_alpha2(const char *alpha2)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_intersected_alpha2(const char *alpha2)
|
||||
{
|
||||
if (!alpha2)
|
||||
return false;
|
||||
/* Special case where regulatory domain is the
|
||||
* result of an intersection between two regulatory domain
|
||||
* structures */
|
||||
if (alpha2[0] == '9' && alpha2[1] == '8')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_an_alpha2(const char *alpha2)
|
||||
{
|
||||
if (!alpha2)
|
||||
@ -292,6 +315,25 @@ static bool regdom_changed(const char *alpha2)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* country_ie_integrity_changes - tells us if the country IE has changed
|
||||
* @checksum: checksum of country IE of fields we are interested in
|
||||
*
|
||||
* If the country IE has not changed you can ignore it safely. This is
|
||||
* useful to determine if two devices are seeing two different country IEs
|
||||
* even on the same alpha2. Note that this will return false if no IE has
|
||||
* been set on the wireless core yet.
|
||||
*/
|
||||
static bool country_ie_integrity_changes(u32 checksum)
|
||||
{
|
||||
/* If no IE has been set then the checksum doesn't change */
|
||||
if (unlikely(!last_request->country_ie_checksum))
|
||||
return false;
|
||||
if (unlikely(last_request->country_ie_checksum != checksum))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This lets us keep regulatory code which is updated on a regulatory
|
||||
* basis in userspace. */
|
||||
static int call_crda(const char *alpha2)
|
||||
@ -330,7 +372,7 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
|
||||
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
|
||||
u32 freq_diff;
|
||||
|
||||
if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0)
|
||||
if (freq_range->start_freq_khz <= 0 || freq_range->end_freq_khz <= 0)
|
||||
return false;
|
||||
|
||||
if (freq_range->start_freq_khz > freq_range->end_freq_khz)
|
||||
@ -352,6 +394,9 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
|
||||
if (!rd->n_reg_rules)
|
||||
return false;
|
||||
|
||||
if (WARN_ON(rd->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < rd->n_reg_rules; i++) {
|
||||
reg_rule = &rd->reg_rules[i];
|
||||
if (!is_valid_reg_rule(reg_rule))
|
||||
@ -376,6 +421,174 @@ static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Converts a country IE to a regulatory domain. A regulatory domain
|
||||
* structure has a lot of information which the IE doesn't yet have,
|
||||
* so for the other values we use upper max values as we will intersect
|
||||
* with our userspace regulatory agent to get lower bounds. */
|
||||
static struct ieee80211_regdomain *country_ie_2_rd(
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len,
|
||||
u32 *checksum)
|
||||
{
|
||||
struct ieee80211_regdomain *rd = NULL;
|
||||
unsigned int i = 0;
|
||||
char alpha2[2];
|
||||
u32 flags = 0;
|
||||
u32 num_rules = 0, size_of_regd = 0;
|
||||
u8 *triplets_start = NULL;
|
||||
u8 len_at_triplet = 0;
|
||||
/* the last channel we have registered in a subband (triplet) */
|
||||
int last_sub_max_channel = 0;
|
||||
|
||||
*checksum = 0xDEADBEEF;
|
||||
|
||||
/* Country IE requirements */
|
||||
BUG_ON(country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN ||
|
||||
country_ie_len & 0x01);
|
||||
|
||||
alpha2[0] = country_ie[0];
|
||||
alpha2[1] = country_ie[1];
|
||||
|
||||
/*
|
||||
* Third octet can be:
|
||||
* 'I' - Indoor
|
||||
* 'O' - Outdoor
|
||||
*
|
||||
* anything else we assume is no restrictions
|
||||
*/
|
||||
if (country_ie[2] == 'I')
|
||||
flags = NL80211_RRF_NO_OUTDOOR;
|
||||
else if (country_ie[2] == 'O')
|
||||
flags = NL80211_RRF_NO_INDOOR;
|
||||
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
|
||||
triplets_start = country_ie;
|
||||
len_at_triplet = country_ie_len;
|
||||
|
||||
*checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8);
|
||||
|
||||
/* We need to build a reg rule for each triplet, but first we must
|
||||
* calculate the number of reg rules we will need. We will need one
|
||||
* for each channel subband */
|
||||
while (country_ie_len >= 3) {
|
||||
struct ieee80211_country_ie_triplet *triplet =
|
||||
(struct ieee80211_country_ie_triplet *) country_ie;
|
||||
int cur_sub_max_channel = 0, cur_channel = 0;
|
||||
|
||||
if (triplet->ext.reg_extension_id >=
|
||||
IEEE80211_COUNTRY_EXTENSION_ID) {
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
cur_channel = triplet->chans.first_channel;
|
||||
cur_sub_max_channel = ieee80211_channel_to_frequency(
|
||||
cur_channel + triplet->chans.num_channels);
|
||||
|
||||
/* Basic sanity check */
|
||||
if (cur_sub_max_channel < cur_channel)
|
||||
return NULL;
|
||||
|
||||
/* Do not allow overlapping channels. Also channels
|
||||
* passed in each subband must be monotonically
|
||||
* increasing */
|
||||
if (last_sub_max_channel) {
|
||||
if (cur_channel <= last_sub_max_channel)
|
||||
return NULL;
|
||||
if (cur_sub_max_channel <= last_sub_max_channel)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* When dot11RegulatoryClassesRequired is supported
|
||||
* we can throw ext triplets as part of this soup,
|
||||
* for now we don't care when those change as we
|
||||
* don't support them */
|
||||
*checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) |
|
||||
((cur_sub_max_channel ^ cur_sub_max_channel) << 16) |
|
||||
((triplet->chans.max_power ^ cur_sub_max_channel) << 24);
|
||||
|
||||
last_sub_max_channel = cur_sub_max_channel;
|
||||
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
num_rules++;
|
||||
|
||||
/* Note: this is not a IEEE requirement but
|
||||
* simply a memory requirement */
|
||||
if (num_rules > NL80211_MAX_SUPP_REG_RULES)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
country_ie = triplets_start;
|
||||
country_ie_len = len_at_triplet;
|
||||
|
||||
size_of_regd = sizeof(struct ieee80211_regdomain) +
|
||||
(num_rules * sizeof(struct ieee80211_reg_rule));
|
||||
|
||||
rd = kzalloc(size_of_regd, GFP_KERNEL);
|
||||
if (!rd)
|
||||
return NULL;
|
||||
|
||||
rd->n_reg_rules = num_rules;
|
||||
rd->alpha2[0] = alpha2[0];
|
||||
rd->alpha2[1] = alpha2[1];
|
||||
|
||||
/* This time around we fill in the rd */
|
||||
while (country_ie_len >= 3) {
|
||||
struct ieee80211_country_ie_triplet *triplet =
|
||||
(struct ieee80211_country_ie_triplet *) country_ie;
|
||||
struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
struct ieee80211_freq_range *freq_range = NULL;
|
||||
struct ieee80211_power_rule *power_rule = NULL;
|
||||
|
||||
/* Must parse if dot11RegulatoryClassesRequired is true,
|
||||
* we don't support this yet */
|
||||
if (triplet->ext.reg_extension_id >=
|
||||
IEEE80211_COUNTRY_EXTENSION_ID) {
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
reg_rule = &rd->reg_rules[i];
|
||||
freq_range = ®_rule->freq_range;
|
||||
power_rule = ®_rule->power_rule;
|
||||
|
||||
reg_rule->flags = flags;
|
||||
|
||||
/* The +10 is since the regulatory domain expects
|
||||
* the actual band edge, not the center of freq for
|
||||
* its start and end freqs, assuming 20 MHz bandwidth on
|
||||
* the channels passed */
|
||||
freq_range->start_freq_khz =
|
||||
MHZ_TO_KHZ(ieee80211_channel_to_frequency(
|
||||
triplet->chans.first_channel) - 10);
|
||||
freq_range->end_freq_khz =
|
||||
MHZ_TO_KHZ(ieee80211_channel_to_frequency(
|
||||
triplet->chans.first_channel +
|
||||
triplet->chans.num_channels) + 10);
|
||||
|
||||
/* Large arbitrary values, we intersect later */
|
||||
/* Increment this if we ever support >= 40 MHz channels
|
||||
* in IEEE 802.11 */
|
||||
freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40);
|
||||
power_rule->max_antenna_gain = DBI_TO_MBI(100);
|
||||
power_rule->max_eirp = DBM_TO_MBM(100);
|
||||
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
i++;
|
||||
|
||||
BUG_ON(i > NL80211_MAX_SUPP_REG_RULES);
|
||||
}
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
||||
|
||||
/* Helper for regdom_intersect(), this does the real
|
||||
* mathematical intersection fun */
|
||||
static int reg_rules_intersect(
|
||||
@ -603,12 +816,23 @@ static void handle_band(struct ieee80211_supported_band *sband)
|
||||
handle_channel(&sband->channels[i]);
|
||||
}
|
||||
|
||||
static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
|
||||
{
|
||||
if (!last_request)
|
||||
return true;
|
||||
if (setby == REGDOM_SET_BY_CORE &&
|
||||
wiphy->fw_handles_regulatory)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void update_all_wiphy_regulatory(enum reg_set_by setby)
|
||||
{
|
||||
struct cfg80211_registered_device *drv;
|
||||
|
||||
list_for_each_entry(drv, &cfg80211_drv_list, list)
|
||||
wiphy_update_regulatory(&drv->wiphy, setby);
|
||||
if (!ignore_reg_update(&drv->wiphy, setby))
|
||||
wiphy_update_regulatory(&drv->wiphy, setby);
|
||||
}
|
||||
|
||||
void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
|
||||
@ -660,16 +884,14 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
|
||||
return -EOPNOTSUPP;
|
||||
return -EALREADY;
|
||||
}
|
||||
/* Two consecutive Country IE hints on the same wiphy */
|
||||
if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
|
||||
/* Two consecutive Country IE hints on the same wiphy.
|
||||
* This should be picked up early by the driver/stack */
|
||||
if (WARN_ON(!alpha2_equal(cfg80211_regdomain->alpha2,
|
||||
alpha2)))
|
||||
return 0;
|
||||
return -EALREADY;
|
||||
}
|
||||
/*
|
||||
* Ignore Country IE hints for now, need to think about
|
||||
* what we need to do to support multi-domain operation.
|
||||
*/
|
||||
return -EOPNOTSUPP;
|
||||
return REG_INTERSECT;
|
||||
case REGDOM_SET_BY_DRIVER:
|
||||
if (last_request->initiator == REGDOM_SET_BY_DRIVER)
|
||||
return -EALREADY;
|
||||
@ -677,6 +899,11 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
|
||||
case REGDOM_SET_BY_USER:
|
||||
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
|
||||
return REG_INTERSECT;
|
||||
/* If the user knows better the user should set the regdom
|
||||
* to their country before the IE is picked up */
|
||||
if (last_request->initiator == REGDOM_SET_BY_USER &&
|
||||
last_request->intersect)
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -685,7 +912,9 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
|
||||
|
||||
/* Caller must hold &cfg80211_drv_mutex */
|
||||
int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
|
||||
const char *alpha2)
|
||||
const char *alpha2,
|
||||
u32 country_ie_checksum,
|
||||
enum environment_cap env)
|
||||
{
|
||||
struct regulatory_request *request;
|
||||
bool intersect = false;
|
||||
@ -698,36 +927,32 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
|
||||
else if (r)
|
||||
return r;
|
||||
|
||||
switch (set_by) {
|
||||
case REGDOM_SET_BY_CORE:
|
||||
case REGDOM_SET_BY_COUNTRY_IE:
|
||||
case REGDOM_SET_BY_DRIVER:
|
||||
case REGDOM_SET_BY_USER:
|
||||
request = kzalloc(sizeof(struct regulatory_request),
|
||||
GFP_KERNEL);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
request = kzalloc(sizeof(struct regulatory_request),
|
||||
GFP_KERNEL);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
|
||||
request->alpha2[0] = alpha2[0];
|
||||
request->alpha2[1] = alpha2[1];
|
||||
request->initiator = set_by;
|
||||
request->wiphy = wiphy;
|
||||
request->intersect = intersect;
|
||||
request->alpha2[0] = alpha2[0];
|
||||
request->alpha2[1] = alpha2[1];
|
||||
request->initiator = set_by;
|
||||
request->wiphy = wiphy;
|
||||
request->intersect = intersect;
|
||||
request->country_ie_checksum = country_ie_checksum;
|
||||
request->country_ie_env = env;
|
||||
|
||||
kfree(last_request);
|
||||
last_request = request;
|
||||
r = call_crda(alpha2);
|
||||
#ifndef CONFIG_WIRELESS_OLD_REGULATORY
|
||||
if (r)
|
||||
printk(KERN_ERR "cfg80211: Failed calling CRDA\n");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
r = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
kfree(last_request);
|
||||
last_request = request;
|
||||
/*
|
||||
* Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled
|
||||
* AND if CRDA is NOT present nothing will happen, if someone
|
||||
* wants to bother with 11d with OLD_REG you can add a timer.
|
||||
* If after x amount of time nothing happens you can call:
|
||||
*
|
||||
* return set_regdom(country_ie_regdomain);
|
||||
*
|
||||
* to intersect with the static rd
|
||||
*/
|
||||
return call_crda(alpha2);
|
||||
}
|
||||
|
||||
void regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
||||
@ -735,11 +960,120 @@ void regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
||||
BUG_ON(!alpha2);
|
||||
|
||||
mutex_lock(&cfg80211_drv_mutex);
|
||||
__regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2);
|
||||
__regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY);
|
||||
mutex_unlock(&cfg80211_drv_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_hint);
|
||||
|
||||
static bool reg_same_country_ie_hint(struct wiphy *wiphy,
|
||||
u32 country_ie_checksum)
|
||||
{
|
||||
if (!last_request->wiphy)
|
||||
return false;
|
||||
if (likely(last_request->wiphy != wiphy))
|
||||
return !country_ie_integrity_changes(country_ie_checksum);
|
||||
/* We should not have let these through at this point, they
|
||||
* should have been picked up earlier by the first alpha2 check
|
||||
* on the device */
|
||||
if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len)
|
||||
{
|
||||
struct ieee80211_regdomain *rd = NULL;
|
||||
char alpha2[2];
|
||||
u32 checksum = 0;
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
|
||||
mutex_lock(&cfg80211_drv_mutex);
|
||||
|
||||
/* IE len must be evenly divisible by 2 */
|
||||
if (country_ie_len & 0x01)
|
||||
goto out;
|
||||
|
||||
if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
|
||||
goto out;
|
||||
|
||||
/* Pending country IE processing, this can happen after we
|
||||
* call CRDA and wait for a response if a beacon was received before
|
||||
* we were able to process the last regulatory_hint_11d() call */
|
||||
if (country_ie_regdomain)
|
||||
goto out;
|
||||
|
||||
alpha2[0] = country_ie[0];
|
||||
alpha2[1] = country_ie[1];
|
||||
|
||||
if (country_ie[2] == 'I')
|
||||
env = ENVIRON_INDOOR;
|
||||
else if (country_ie[2] == 'O')
|
||||
env = ENVIRON_OUTDOOR;
|
||||
|
||||
/* We will run this for *every* beacon processed for the BSSID, so
|
||||
* we optimize an early check to exit out early if we don't have to
|
||||
* do anything */
|
||||
if (likely(last_request->wiphy)) {
|
||||
struct cfg80211_registered_device *drv_last_ie;
|
||||
|
||||
drv_last_ie = wiphy_to_dev(last_request->wiphy);
|
||||
|
||||
/* Lets keep this simple -- we trust the first AP
|
||||
* after we intersect with CRDA */
|
||||
if (likely(last_request->wiphy == wiphy)) {
|
||||
/* Ignore IEs coming in on this wiphy with
|
||||
* the same alpha2 and environment cap */
|
||||
if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
|
||||
alpha2) &&
|
||||
env == drv_last_ie->env)) {
|
||||
goto out;
|
||||
}
|
||||
/* the wiphy moved on to another BSSID or the AP
|
||||
* was reconfigured. XXX: We need to deal with the
|
||||
* case where the user suspends and goes to goes
|
||||
* to another country, and then gets IEs from an
|
||||
* AP with different settings */
|
||||
goto out;
|
||||
} else {
|
||||
/* Ignore IEs coming in on two separate wiphys with
|
||||
* the same alpha2 and environment cap */
|
||||
if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
|
||||
alpha2) &&
|
||||
env == drv_last_ie->env)) {
|
||||
goto out;
|
||||
}
|
||||
/* We could potentially intersect though */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rd = country_ie_2_rd(country_ie, country_ie_len, &checksum);
|
||||
if (!rd)
|
||||
goto out;
|
||||
|
||||
/* This will not happen right now but we leave it here for the
|
||||
* the future when we want to add suspend/resume support and having
|
||||
* the user move to another country after doing so, or having the user
|
||||
* move to another AP. Right now we just trust the first AP. This is why
|
||||
* this is marked as likley(). If we hit this before we add this support
|
||||
* we want to be informed of it as it would indicate a mistake in the
|
||||
* current design */
|
||||
if (likely(WARN_ON(reg_same_country_ie_hint(wiphy, checksum))))
|
||||
goto out;
|
||||
|
||||
/* We keep this around for when CRDA comes back with a response so
|
||||
* we can intersect with that */
|
||||
country_ie_regdomain = rd;
|
||||
|
||||
__regulatory_hint(wiphy, REGDOM_SET_BY_COUNTRY_IE,
|
||||
country_ie_regdomain->alpha2, checksum, env);
|
||||
|
||||
out:
|
||||
mutex_unlock(&cfg80211_drv_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_hint_11d);
|
||||
|
||||
static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
@ -779,7 +1113,25 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
||||
static void print_regdomain(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
|
||||
if (is_world_regdom(rd->alpha2))
|
||||
if (is_intersected_alpha2(rd->alpha2)) {
|
||||
struct wiphy *wiphy = NULL;
|
||||
struct cfg80211_registered_device *drv;
|
||||
|
||||
if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
|
||||
if (last_request->wiphy) {
|
||||
wiphy = last_request->wiphy;
|
||||
drv = wiphy_to_dev(wiphy);
|
||||
printk(KERN_INFO "cfg80211: Current regulatory "
|
||||
"domain updated by AP to: %c%c\n",
|
||||
drv->country_ie_alpha2[0],
|
||||
drv->country_ie_alpha2[1]);
|
||||
} else
|
||||
printk(KERN_INFO "cfg80211: Current regulatory "
|
||||
"domain intersected: \n");
|
||||
} else
|
||||
printk(KERN_INFO "cfg80211: Current regulatory "
|
||||
"intersected: \n");
|
||||
} else if (is_world_regdom(rd->alpha2))
|
||||
printk(KERN_INFO "cfg80211: World regulatory "
|
||||
"domain updated:\n");
|
||||
else {
|
||||
@ -802,10 +1154,39 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
|
||||
print_rd_rules(rd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CFG80211_REG_DEBUG
|
||||
static void reg_country_ie_process_debug(
|
||||
const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_regdomain *country_ie_regdomain,
|
||||
const struct ieee80211_regdomain *intersected_rd)
|
||||
{
|
||||
printk(KERN_DEBUG "cfg80211: Received country IE:\n");
|
||||
print_regdomain_info(country_ie_regdomain);
|
||||
printk(KERN_DEBUG "cfg80211: CRDA thinks this should applied:\n");
|
||||
print_regdomain_info(rd);
|
||||
if (intersected_rd) {
|
||||
printk(KERN_DEBUG "cfg80211: We intersect both of these "
|
||||
"and get:\n");
|
||||
print_regdomain_info(rd);
|
||||
return;
|
||||
}
|
||||
printk(KERN_DEBUG "cfg80211: Intersection between both failed\n");
|
||||
}
|
||||
#else
|
||||
static inline void reg_country_ie_process_debug(
|
||||
const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_regdomain *country_ie_regdomain,
|
||||
const struct ieee80211_regdomain *intersected_rd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Takes ownership of rd only if it doesn't fail */
|
||||
static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
const struct ieee80211_regdomain *intersected_rd = NULL;
|
||||
struct cfg80211_registered_device *drv = NULL;
|
||||
struct wiphy *wiphy = NULL;
|
||||
/* Some basic sanity checks first */
|
||||
|
||||
if (is_world_regdom(rd->alpha2)) {
|
||||
@ -822,10 +1203,18 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
if (!last_request)
|
||||
return -EINVAL;
|
||||
|
||||
/* allow overriding the static definitions if CRDA is present */
|
||||
if (!is_old_static_regdom(cfg80211_regdomain) &&
|
||||
!regdom_changed(rd->alpha2))
|
||||
return -EINVAL;
|
||||
/* Lets only bother proceeding on the same alpha2 if the current
|
||||
* rd is non static (it means CRDA was present and was used last)
|
||||
* and the pending request came in from a country IE */
|
||||
if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) {
|
||||
/* If someone else asked us to change the rd lets only bother
|
||||
* checking if the alpha2 changes if CRDA was already called */
|
||||
if (!is_old_static_regdom(cfg80211_regdomain) &&
|
||||
!regdom_changed(rd->alpha2))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wiphy = last_request->wiphy;
|
||||
|
||||
/* Now lets set the regulatory domain, update all driver channels
|
||||
* and finally inform them of what we have done, in case they want
|
||||
@ -835,36 +1224,78 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
|
||||
return -EINVAL;
|
||||
|
||||
reset_regdomains();
|
||||
|
||||
/* Country IE parsing coming soon */
|
||||
switch (last_request->initiator) {
|
||||
case REGDOM_SET_BY_CORE:
|
||||
case REGDOM_SET_BY_DRIVER:
|
||||
case REGDOM_SET_BY_USER:
|
||||
if (!is_valid_rd(rd)) {
|
||||
printk(KERN_ERR "cfg80211: Invalid "
|
||||
"regulatory domain detected:\n");
|
||||
print_regdomain_info(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case REGDOM_SET_BY_COUNTRY_IE: /* Not yet */
|
||||
WARN_ON(1);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
if (!is_valid_rd(rd)) {
|
||||
printk(KERN_ERR "cfg80211: Invalid "
|
||||
"regulatory domain detected:\n");
|
||||
print_regdomain_info(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely(last_request->intersect)) {
|
||||
if (!last_request->intersect) {
|
||||
reset_regdomains();
|
||||
cfg80211_regdomain = rd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Intersection requires a bit more work */
|
||||
|
||||
if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) {
|
||||
|
||||
intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
|
||||
if (!intersected_rd)
|
||||
return -EINVAL;
|
||||
|
||||
/* We can trash what CRDA provided now */
|
||||
kfree(rd);
|
||||
rd = intersected_rd;
|
||||
rd = NULL;
|
||||
|
||||
reset_regdomains();
|
||||
cfg80211_regdomain = intersected_rd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tada! */
|
||||
cfg80211_regdomain = rd;
|
||||
/*
|
||||
* Country IE requests are handled a bit differently, we intersect
|
||||
* the country IE rd with what CRDA believes that country should have
|
||||
*/
|
||||
|
||||
BUG_ON(!country_ie_regdomain);
|
||||
|
||||
if (rd != country_ie_regdomain) {
|
||||
/* Intersect what CRDA returned and our what we
|
||||
* had built from the Country IE received */
|
||||
|
||||
intersected_rd = regdom_intersect(rd, country_ie_regdomain);
|
||||
|
||||
reg_country_ie_process_debug(rd, country_ie_regdomain,
|
||||
intersected_rd);
|
||||
|
||||
kfree(country_ie_regdomain);
|
||||
country_ie_regdomain = NULL;
|
||||
} else {
|
||||
/* This would happen when CRDA was not present and
|
||||
* OLD_REGULATORY was enabled. We intersect our Country
|
||||
* IE rd and what was set on cfg80211 originally */
|
||||
intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
|
||||
}
|
||||
|
||||
if (!intersected_rd)
|
||||
return -EINVAL;
|
||||
|
||||
drv = wiphy_to_dev(wiphy);
|
||||
|
||||
drv->country_ie_alpha2[0] = rd->alpha2[0];
|
||||
drv->country_ie_alpha2[1] = rd->alpha2[1];
|
||||
drv->env = last_request->country_ie_env;
|
||||
|
||||
BUG_ON(intersected_rd == rd);
|
||||
|
||||
kfree(rd);
|
||||
rd = NULL;
|
||||
|
||||
reset_regdomains();
|
||||
cfg80211_regdomain = intersected_rd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -885,16 +1316,28 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
||||
}
|
||||
|
||||
/* This would make this whole thing pointless */
|
||||
BUG_ON(rd != cfg80211_regdomain);
|
||||
if (!last_request->intersect)
|
||||
BUG_ON(rd != cfg80211_regdomain);
|
||||
|
||||
/* update all wiphys now with the new established regulatory domain */
|
||||
update_all_wiphy_regulatory(last_request->initiator);
|
||||
|
||||
print_regdomain(rd);
|
||||
print_regdomain(cfg80211_regdomain);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Caller must hold cfg80211_drv_mutex */
|
||||
void reg_device_remove(struct wiphy *wiphy)
|
||||
{
|
||||
if (!last_request->wiphy)
|
||||
return;
|
||||
if (last_request->wiphy != wiphy)
|
||||
return;
|
||||
last_request->wiphy = NULL;
|
||||
last_request->country_ie_env = ENVIRON_ANY;
|
||||
}
|
||||
|
||||
int regulatory_init(void)
|
||||
{
|
||||
int err;
|
||||
@ -914,11 +1357,11 @@ int regulatory_init(void)
|
||||
* that is not a valid ISO / IEC 3166 alpha2 */
|
||||
if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U')
|
||||
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
|
||||
ieee80211_regdom);
|
||||
ieee80211_regdom, 0, ENVIRON_ANY);
|
||||
#else
|
||||
cfg80211_regdomain = cfg80211_world_regdom;
|
||||
|
||||
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00");
|
||||
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", 0, ENVIRON_ANY);
|
||||
if (err)
|
||||
printk(KERN_ERR "cfg80211: calling CRDA failed - "
|
||||
"unable to update world regulatory domain, "
|
||||
@ -934,6 +1377,9 @@ void regulatory_exit(void)
|
||||
|
||||
reset_regdomains();
|
||||
|
||||
kfree(country_ie_regdomain);
|
||||
country_ie_regdomain = NULL;
|
||||
|
||||
kfree(last_request);
|
||||
|
||||
platform_device_unregister(reg_pdev);
|
||||
|
@ -4,28 +4,41 @@
|
||||
bool is_world_regdom(const char *alpha2);
|
||||
bool reg_is_valid_request(const char *alpha2);
|
||||
|
||||
void reg_device_remove(struct wiphy *wiphy);
|
||||
|
||||
int regulatory_init(void);
|
||||
void regulatory_exit(void);
|
||||
|
||||
int set_regdom(const struct ieee80211_regdomain *rd);
|
||||
|
||||
enum environment_cap {
|
||||
ENVIRON_ANY,
|
||||
ENVIRON_INDOOR,
|
||||
ENVIRON_OUTDOOR,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* __regulatory_hint - hint to the wireless core a regulatory domain
|
||||
* @wiphy: if the hint comes from country information from an AP, this
|
||||
* is required to be set to the wiphy that received the information
|
||||
* @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain
|
||||
* should be in.
|
||||
* @country_ie_checksum: checksum of processed country IE, set this to 0
|
||||
* if the hint did not come from a country IE
|
||||
* @country_ie_env: the environment the IE told us we are in, %ENVIRON_*
|
||||
*
|
||||
* The Wireless subsystem can use this function to hint to the wireless core
|
||||
* what it believes should be the current regulatory domain by
|
||||
* giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
|
||||
* domain should be in.
|
||||
* what it believes should be the current regulatory domain by giving it an
|
||||
* ISO/IEC 3166 alpha2 country code it knows its regulatory domain should be
|
||||
* in.
|
||||
*
|
||||
* Returns zero if all went fine, %-EALREADY if a regulatory domain had
|
||||
* already been set or other standard error codes.
|
||||
*
|
||||
*/
|
||||
extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
|
||||
const char *alpha2);
|
||||
const char *alpha2, u32 country_ie_checksum,
|
||||
enum environment_cap country_ie_env);
|
||||
|
||||
#endif /* __NET_WIRELESS_REG_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user