mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-12 16:58:53 +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
8aa0f64ac3
@ -5,6 +5,7 @@
|
||||
menuconfig WLAN
|
||||
bool "Wireless LAN"
|
||||
depends on !S390
|
||||
select WIRELESS
|
||||
default y
|
||||
---help---
|
||||
This section contains all the pre 802.11 and 802.11 wireless
|
||||
@ -67,6 +68,8 @@ config WAVELAN
|
||||
tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
|
||||
depends on ISA && WLAN_PRE80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
|
||||
a Radio LAN (wireless Ethernet-like Local Area Network) using the
|
||||
@ -90,6 +93,8 @@ config PCMCIA_WAVELAN
|
||||
tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
|
||||
depends on PCMCIA && WLAN_PRE80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
help
|
||||
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer. This
|
||||
@ -102,6 +107,7 @@ config PCMCIA_NETWAVE
|
||||
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
|
||||
depends on PCMCIA && WLAN_PRE80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
help
|
||||
Say Y here if you intend to attach this type of PCMCIA (PC-card)
|
||||
wireless Ethernet networking card to your computer.
|
||||
@ -123,6 +129,8 @@ config PCMCIA_RAYCS
|
||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
depends on PCMCIA && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer.
|
||||
@ -132,46 +140,6 @@ config PCMCIA_RAYCS
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ray_cs. If unsure, say N.
|
||||
|
||||
config LIBERTAS
|
||||
tristate "Marvell 8xxx Libertas WLAN driver support"
|
||||
depends on WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select LIB80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A library for Marvell Libertas 8xxx devices.
|
||||
|
||||
config LIBERTAS_USB
|
||||
tristate "Marvell Libertas 8388 USB 802.11b/g cards"
|
||||
depends on LIBERTAS && USB
|
||||
---help---
|
||||
A driver for Marvell Libertas 8388 USB devices.
|
||||
|
||||
config LIBERTAS_CS
|
||||
tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
|
||||
depends on LIBERTAS && PCMCIA
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385 CompactFlash devices.
|
||||
|
||||
config LIBERTAS_SDIO
|
||||
tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
|
||||
depends on LIBERTAS && MMC
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
|
||||
|
||||
config LIBERTAS_SPI
|
||||
tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
|
||||
depends on LIBERTAS && SPI
|
||||
---help---
|
||||
A driver for Marvell Libertas 8686 SPI devices.
|
||||
|
||||
config LIBERTAS_DEBUG
|
||||
bool "Enable full debugging output in the Libertas module."
|
||||
depends on LIBERTAS
|
||||
---help---
|
||||
Debugging support.
|
||||
|
||||
config LIBERTAS_THINFIRM
|
||||
tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
|
||||
depends on WLAN_80211 && MAC80211
|
||||
@ -190,6 +158,8 @@ config AIRO
|
||||
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
|
||||
select WIRELESS_EXT
|
||||
select CRYPTO
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
This is the standard Linux driver to support Cisco/Aironet ISA and
|
||||
PCI 802.11 wireless cards.
|
||||
@ -207,6 +177,7 @@ config ATMEL
|
||||
tristate "Atmel at76c50x chipset 802.11b support"
|
||||
depends on (PCI || PCMCIA) && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select CRC32
|
||||
---help---
|
||||
@ -266,18 +237,21 @@ config AIRO_CS
|
||||
Cisco Linux utilities can be used to configure the card.
|
||||
|
||||
config PCMCIA_WL3501
|
||||
tristate "Planet WL3501 PCMCIA cards"
|
||||
depends on EXPERIMENTAL && PCMCIA && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
---help---
|
||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||
It has basic support for Linux wireless extensions and initial
|
||||
micro support for ethtool.
|
||||
tristate "Planet WL3501 PCMCIA cards"
|
||||
depends on EXPERIMENTAL && PCMCIA && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
help
|
||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||
It has basic support for Linux wireless extensions and initial
|
||||
micro support for ethtool.
|
||||
|
||||
config PRISM54
|
||||
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
|
||||
depends on PCI && EXPERIMENTAL && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This enables support for FullMAC PCI/Cardbus prism54 devices. This
|
||||
@ -300,6 +274,7 @@ config USB_ZD1201
|
||||
tristate "USB ZD1201 based Wireless device support"
|
||||
depends on USB && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
---help---
|
||||
Say Y if you want to use wireless LAN adapters based on the ZyDAS
|
||||
@ -476,17 +451,18 @@ config MWL8K
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mwl8k. If unsure, say N.
|
||||
|
||||
source "drivers/net/wireless/p54/Kconfig"
|
||||
source "drivers/net/wireless/ath/Kconfig"
|
||||
source "drivers/net/wireless/ipw2x00/Kconfig"
|
||||
source "drivers/net/wireless/iwlwifi/Kconfig"
|
||||
source "drivers/net/wireless/hostap/Kconfig"
|
||||
source "drivers/net/wireless/b43/Kconfig"
|
||||
source "drivers/net/wireless/b43legacy/Kconfig"
|
||||
source "drivers/net/wireless/zd1211rw/Kconfig"
|
||||
source "drivers/net/wireless/rt2x00/Kconfig"
|
||||
source "drivers/net/wireless/orinoco/Kconfig"
|
||||
source "drivers/net/wireless/wl12xx/Kconfig"
|
||||
source "drivers/net/wireless/hostap/Kconfig"
|
||||
source "drivers/net/wireless/ipw2x00/Kconfig"
|
||||
source "drivers/net/wireless/iwlwifi/Kconfig"
|
||||
source "drivers/net/wireless/iwmc3200wifi/Kconfig"
|
||||
source "drivers/net/wireless/libertas/Kconfig"
|
||||
source "drivers/net/wireless/orinoco/Kconfig"
|
||||
source "drivers/net/wireless/p54/Kconfig"
|
||||
source "drivers/net/wireless/rt2x00/Kconfig"
|
||||
source "drivers/net/wireless/wl12xx/Kconfig"
|
||||
source "drivers/net/wireless/zd1211rw/Kconfig"
|
||||
|
||||
endif # WLAN
|
||||
|
@ -2217,6 +2217,8 @@ static struct ieee80211_supported_band at76_supported_band = {
|
||||
static int at76_init_new_device(struct at76_priv *priv,
|
||||
struct usb_interface *interface)
|
||||
{
|
||||
struct wiphy *wiphy;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
/* set up the endpoint information */
|
||||
@ -2254,6 +2256,7 @@ static int at76_init_new_device(struct at76_priv *priv,
|
||||
priv->device_unplugged = 0;
|
||||
|
||||
/* mac80211 initialisation */
|
||||
wiphy = priv->hw->wiphy;
|
||||
priv->hw->wiphy->max_scan_ssids = 1;
|
||||
priv->hw->wiphy->max_scan_ie_len = 0;
|
||||
priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
@ -2265,6 +2268,13 @@ static int at76_init_new_device(struct at76_priv *priv,
|
||||
SET_IEEE80211_DEV(priv->hw, &interface->dev);
|
||||
SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
|
||||
|
||||
len = sizeof(wiphy->fw_version);
|
||||
snprintf(wiphy->fw_version, len, "%d.%d.%d-%d",
|
||||
priv->fw_version.major, priv->fw_version.minor,
|
||||
priv->fw_version.patch, priv->fw_version.build);
|
||||
|
||||
wiphy->hw_version = priv->board_type;
|
||||
|
||||
ret = ieee80211_register_hw(priv->hw);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n",
|
||||
|
@ -16,7 +16,15 @@ menuconfig ATH_COMMON
|
||||
http://wireless.kernel.org/en/users/Drivers/Atheros
|
||||
|
||||
if ATH_COMMON
|
||||
|
||||
config ATH_DEBUG
|
||||
bool "Atheros wireless debugging"
|
||||
---help---
|
||||
Say Y, if you want to debug atheros wireless drivers.
|
||||
Right now only ath9k makes use of this.
|
||||
|
||||
source "drivers/net/wireless/ath/ath5k/Kconfig"
|
||||
source "drivers/net/wireless/ath/ath9k/Kconfig"
|
||||
source "drivers/net/wireless/ath/ar9170/Kconfig"
|
||||
|
||||
endif
|
||||
|
@ -1,6 +1,11 @@
|
||||
obj-$(CONFIG_ATH5K) += ath5k/
|
||||
obj-$(CONFIG_ATH9K) += ath9k/
|
||||
obj-$(CONFIG_ATH9K_HW) += ath9k/
|
||||
obj-$(CONFIG_AR9170_USB) += ar9170/
|
||||
|
||||
obj-$(CONFIG_ATH_COMMON) += ath.o
|
||||
ath-objs := main.o regd.o
|
||||
|
||||
ath-objs := main.o \
|
||||
regd.o \
|
||||
hw.o
|
||||
|
||||
ath-$(CONFIG_ATH_DEBUG) += debug.o
|
||||
|
@ -172,8 +172,6 @@ struct ar9170 {
|
||||
|
||||
/* interface mode settings */
|
||||
struct ieee80211_vif *vif;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
/* beaconing */
|
||||
struct sk_buff *beacon;
|
||||
@ -204,6 +202,8 @@ struct ar9170 {
|
||||
u8 power_2G_ht20[8];
|
||||
u8 power_2G_ht40[8];
|
||||
|
||||
u8 phy_heavy_clip;
|
||||
|
||||
#ifdef CONFIG_AR9170_LEDS
|
||||
struct delayed_work led_work;
|
||||
struct ar9170_led leds[AR9170_NUM_LEDS];
|
||||
|
@ -72,8 +72,7 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ar9170_read_mreg(struct ar9170 *ar, int nregs,
|
||||
const u32 *regs, u32 *out)
|
||||
int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out)
|
||||
{
|
||||
int i, err;
|
||||
__le32 *offs, *res;
|
||||
|
@ -44,6 +44,7 @@
|
||||
int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
|
||||
int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
|
||||
int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
|
||||
int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out);
|
||||
int ar9170_echo_test(struct ar9170 *ar, u32 v);
|
||||
|
||||
/*
|
||||
|
@ -311,6 +311,8 @@ struct ar9170_tx_control {
|
||||
|
||||
#define AR9170_TX_PHY_SHORT_GI 0x80000000
|
||||
|
||||
#define AR5416_MAX_RATE_POWER 63
|
||||
|
||||
struct ar9170_rx_head {
|
||||
u8 plcp[12];
|
||||
} __packed;
|
||||
|
@ -35,6 +35,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "ar9170.h"
|
||||
#include "cmd.h"
|
||||
|
||||
@ -227,11 +230,8 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac)
|
||||
|
||||
ar9170_regwrite_begin(ar);
|
||||
|
||||
ar9170_regwrite(reg,
|
||||
(mac[3] << 24) | (mac[2] << 16) |
|
||||
(mac[1] << 8) | mac[0]);
|
||||
|
||||
ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]);
|
||||
ar9170_regwrite(reg, get_unaligned_le32(mac));
|
||||
ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4));
|
||||
|
||||
ar9170_regwrite_finish();
|
||||
|
||||
@ -311,13 +311,14 @@ static int ar9170_set_promiscouous(struct ar9170 *ar)
|
||||
|
||||
int ar9170_set_operating_mode(struct ar9170 *ar)
|
||||
{
|
||||
struct ath_common *common = &ar->common;
|
||||
u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS;
|
||||
u8 *mac_addr, *bssid;
|
||||
int err;
|
||||
|
||||
if (ar->vif) {
|
||||
mac_addr = ar->mac_addr;
|
||||
bssid = ar->bssid;
|
||||
mac_addr = common->macaddr;
|
||||
bssid = common->curbssid;
|
||||
|
||||
switch (ar->vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
|
@ -1952,6 +1952,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ath_common *common = &ar->common;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
@ -1962,7 +1963,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
ar->vif = conf->vif;
|
||||
memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN);
|
||||
memcpy(common->macaddr, conf->mac_addr, ETH_ALEN);
|
||||
|
||||
if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
|
||||
ar->rx_software_decryption = true;
|
||||
@ -2131,12 +2132,13 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
u32 changed)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ath_common *common = &ar->common;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
|
||||
if (changed & BSS_CHANGED_BSSID) {
|
||||
memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
|
||||
err = ar9170_set_operating_mode(ar);
|
||||
if (err)
|
||||
goto out;
|
||||
@ -2190,22 +2192,30 @@ static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
int err;
|
||||
u32 tsf_low;
|
||||
u32 tsf_high;
|
||||
u64 tsf;
|
||||
#define NR 3
|
||||
static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H,
|
||||
AR9170_MAC_REG_TSF_L,
|
||||
AR9170_MAC_REG_TSF_H };
|
||||
u32 val[NR];
|
||||
int loops = 0;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low);
|
||||
if (!err)
|
||||
err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high);
|
||||
|
||||
while (loops++ < 10) {
|
||||
err = ar9170_read_mreg(ar, NR, addr, val);
|
||||
if (err || val[0] == val[2])
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->mutex);
|
||||
|
||||
if (WARN_ON(err))
|
||||
return 0;
|
||||
|
||||
tsf = tsf_high;
|
||||
tsf = (tsf << 32) | tsf_low;
|
||||
tsf = val[0];
|
||||
tsf = (tsf << 32) | val[1];
|
||||
return tsf;
|
||||
#undef NR
|
||||
}
|
||||
|
||||
static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
@ -1239,9 +1239,6 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar,
|
||||
struct ar9170_calctl_edges edges[],
|
||||
u32 freq)
|
||||
{
|
||||
/* TODO: move somewhere else */
|
||||
#define AR5416_MAX_RATE_POWER 63
|
||||
|
||||
int i;
|
||||
u8 rc = AR5416_MAX_RATE_POWER;
|
||||
u8 f;
|
||||
@ -1259,10 +1256,11 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar,
|
||||
break;
|
||||
}
|
||||
if (i > 0 && f < edges[i].channel) {
|
||||
if (f > edges[i-1].channel &&
|
||||
edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
|
||||
if (f > edges[i - 1].channel &&
|
||||
edges[i - 1].power_flags &
|
||||
AR9170_CALCTL_EDGE_FLAGS) {
|
||||
/* lower channel has the inband flag set */
|
||||
rc = edges[i-1].power_flags &
|
||||
rc = edges[i - 1].power_flags &
|
||||
~AR9170_CALCTL_EDGE_FLAGS;
|
||||
}
|
||||
break;
|
||||
@ -1270,18 +1268,48 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar,
|
||||
}
|
||||
|
||||
if (i == AR5416_NUM_BAND_EDGES) {
|
||||
if (f > edges[i-1].channel &&
|
||||
edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
|
||||
if (f > edges[i - 1].channel &&
|
||||
edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
|
||||
/* lower channel has the inband flag set */
|
||||
rc = edges[i-1].power_flags &
|
||||
rc = edges[i - 1].power_flags &
|
||||
~AR9170_CALCTL_EDGE_FLAGS;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* calculate the conformance test limits and apply them to ar->power*
|
||||
* (derived from otus hal/hpmain.c, line 3706 ff.)
|
||||
static u8 ar9170_get_heavy_clip(struct ar9170 *ar,
|
||||
struct ar9170_calctl_edges edges[],
|
||||
u32 freq, enum ar9170_bw bw)
|
||||
{
|
||||
u8 f;
|
||||
int i;
|
||||
u8 rc = 0;
|
||||
|
||||
if (freq < 3000)
|
||||
f = freq - 2300;
|
||||
else
|
||||
f = (freq - 4800) / 5;
|
||||
|
||||
if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE)
|
||||
rc |= 0xf0;
|
||||
|
||||
for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
|
||||
if (edges[i].channel == 0xff)
|
||||
break;
|
||||
if (f == edges[i].channel) {
|
||||
if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS))
|
||||
rc |= 0x0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate the conformance test limits and the heavy clip parameter
|
||||
* and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706)
|
||||
*/
|
||||
static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
{
|
||||
@ -1295,7 +1323,8 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
int pwr_cal_len;
|
||||
} *modes;
|
||||
|
||||
/* order is relevant in the mode_list_*: we fall back to the
|
||||
/*
|
||||
* order is relevant in the mode_list_*: we fall back to the
|
||||
* lower indices if any mode is missed in the EEPROM.
|
||||
*/
|
||||
struct ctl_modes mode_list_2ghz[] = {
|
||||
@ -1313,7 +1342,10 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
|
||||
#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n])
|
||||
|
||||
/* TODO: investigate the differences between OTUS'
|
||||
ar->phy_heavy_clip = 0;
|
||||
|
||||
/*
|
||||
* TODO: investigate the differences between OTUS'
|
||||
* hpreg.c::zfHpGetRegulatoryDomain() and
|
||||
* ath/regd.c::ath_regd_get_band_ctl() -
|
||||
* e.g. for FCC3_WORLD the OTUS procedure
|
||||
@ -1347,6 +1379,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
if (ctl_idx < AR5416_NUM_CTLS) {
|
||||
int f_off = 0;
|
||||
|
||||
/* determine heav clip parameter from
|
||||
the 11G edges array */
|
||||
if (modes[i].ctl_mode == CTL_11G) {
|
||||
ar->phy_heavy_clip =
|
||||
ar9170_get_heavy_clip(ar,
|
||||
EDGES(ctl_idx, 1),
|
||||
freq, bw);
|
||||
}
|
||||
|
||||
/* adjust freq for 40MHz */
|
||||
if (modes[i].ctl_mode == CTL_2GHT40 ||
|
||||
modes[i].ctl_mode == CTL_5GHT40) {
|
||||
@ -1360,13 +1401,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1),
|
||||
freq+f_off);
|
||||
|
||||
/* TODO: check if the regulatory max. power is
|
||||
/*
|
||||
* TODO: check if the regulatory max. power is
|
||||
* controlled by cfg80211 for DFS
|
||||
* (hpmain applies it to max_power itself for DFS freq)
|
||||
*/
|
||||
|
||||
} else {
|
||||
/* Workaround in otus driver, hpmain.c, line 3906:
|
||||
/*
|
||||
* Workaround in otus driver, hpmain.c, line 3906:
|
||||
* if no data for 5GHT20 are found, take the
|
||||
* legacy 5G value.
|
||||
* We extend this here to fallback from any other *HT or
|
||||
@ -1390,6 +1433,19 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
modes[i].max_power);
|
||||
}
|
||||
}
|
||||
|
||||
if (ar->phy_heavy_clip & 0xf0) {
|
||||
ar->power_2G_ht40[0]--;
|
||||
ar->power_2G_ht40[1]--;
|
||||
ar->power_2G_ht40[2]--;
|
||||
}
|
||||
if (ar->phy_heavy_clip & 0xf) {
|
||||
ar->power_2G_ht20[0]++;
|
||||
ar->power_2G_ht20[1]++;
|
||||
ar->power_2G_ht20[2]++;
|
||||
}
|
||||
|
||||
|
||||
#undef EDGES
|
||||
}
|
||||
|
||||
@ -1499,8 +1555,6 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
|
||||
/* calc. conformance test limits and apply to ar->power*[] */
|
||||
ar9170_calc_ctl(ar, freq, bw);
|
||||
|
||||
/* TODO: (heavy clip) regulatory domain power level fine-tuning. */
|
||||
|
||||
/* set ACK/CTS TX power */
|
||||
ar9170_regwrite_begin(ar);
|
||||
|
||||
@ -1643,6 +1697,17 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ar->phy_heavy_clip) {
|
||||
err = ar9170_write_reg(ar, 0x1c59e0,
|
||||
0x200 | ar->phy_heavy_clip);
|
||||
if (err) {
|
||||
if (ar9170_nag_limiter(ar))
|
||||
printk(KERN_ERR "%s: failed to set "
|
||||
"heavy clip\n",
|
||||
wiphy_name(ar->hw->wiphy));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ar->noise[i] = ar9170_calc_noise_dbm(
|
||||
(le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff);
|
||||
|
@ -18,6 +18,15 @@
|
||||
#define ATH_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
enum ath_device_state {
|
||||
ATH_HW_UNAVAILABLE,
|
||||
ATH_HW_INITIALIZED,
|
||||
};
|
||||
|
||||
struct reg_dmn_pair_mapping {
|
||||
u16 regDmnEnum;
|
||||
@ -36,13 +45,45 @@ struct ath_regulatory {
|
||||
struct reg_dmn_pair_mapping *regpair;
|
||||
};
|
||||
|
||||
struct ath_ops {
|
||||
unsigned int (*read)(void *, u32 reg_offset);
|
||||
void (*write)(void *, u32 val, u32 reg_offset);
|
||||
};
|
||||
|
||||
struct ath_common;
|
||||
|
||||
struct ath_bus_ops {
|
||||
void (*read_cachesize)(struct ath_common *common, int *csz);
|
||||
void (*cleanup)(struct ath_common *common);
|
||||
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
||||
void (*bt_coex_prep)(struct ath_common *common);
|
||||
};
|
||||
|
||||
struct ath_common {
|
||||
void *ah;
|
||||
void *priv;
|
||||
struct ieee80211_hw *hw;
|
||||
int debug_mask;
|
||||
enum ath_device_state state;
|
||||
|
||||
u16 cachelsz;
|
||||
u16 curaid;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
u8 curbssid[ETH_ALEN];
|
||||
u8 bssidmask[ETH_ALEN];
|
||||
|
||||
u8 tx_chainmask;
|
||||
u8 rx_chainmask;
|
||||
|
||||
struct ath_regulatory regulatory;
|
||||
const struct ath_ops *ops;
|
||||
const struct ath_bus_ops *bus_ops;
|
||||
};
|
||||
|
||||
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
|
||||
u32 len,
|
||||
gfp_t gfp_mask);
|
||||
|
||||
void ath_hw_setbssidmask(struct ath_common *common);
|
||||
|
||||
#endif /* ATH_H */
|
||||
|
@ -35,6 +35,7 @@
|
||||
* TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
|
||||
* and clean up common bits, then introduce set/get functions in eeprom.c */
|
||||
#include "eeprom.h"
|
||||
#include "../ath.h"
|
||||
|
||||
/* PCI IDs */
|
||||
#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
|
||||
@ -165,13 +166,6 @@
|
||||
#define AR5K_INI_VAL_XR 0
|
||||
#define AR5K_INI_VAL_MAX 5
|
||||
|
||||
/* Used for BSSID etc manipulation */
|
||||
#define AR5K_LOW_ID(_a)( \
|
||||
(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
|
||||
)
|
||||
|
||||
#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
|
||||
|
||||
/*
|
||||
* Some tuneable values (these should be changeable by the user)
|
||||
* TODO: Make use of them and add more options OR use debug/configfs
|
||||
@ -1027,6 +1021,7 @@ struct ath5k_capabilities {
|
||||
/* TODO: Clean up and merge with ath5k_softc */
|
||||
struct ath5k_hw {
|
||||
u32 ah_magic;
|
||||
struct ath_common common;
|
||||
|
||||
struct ath5k_softc *ah_sc;
|
||||
void __iomem *ah_iobase;
|
||||
@ -1067,14 +1062,6 @@ struct ath5k_hw {
|
||||
u8 ah_def_ant;
|
||||
bool ah_software_retry;
|
||||
|
||||
u8 ah_sta_id[ETH_ALEN];
|
||||
|
||||
/* Current BSSID we are trying to assoc to / create.
|
||||
* This is passed by mac80211 on config_interface() and cached here for
|
||||
* use in resets */
|
||||
u8 ah_bssid[ETH_ALEN];
|
||||
u8 ah_bssid_mask[ETH_ALEN];
|
||||
|
||||
int ah_gpio_npins;
|
||||
|
||||
struct ath5k_capabilities ah_capabilities;
|
||||
@ -1160,7 +1147,7 @@ struct ath5k_hw {
|
||||
*/
|
||||
|
||||
/* Attach/Detach Functions */
|
||||
extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc);
|
||||
extern int ath5k_hw_attach(struct ath5k_softc *sc);
|
||||
extern void ath5k_hw_detach(struct ath5k_hw *ah);
|
||||
|
||||
/* LED functions */
|
||||
@ -1203,10 +1190,9 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
|
||||
/* Protocol Control Unit Functions */
|
||||
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
|
||||
/* BSSID Functions */
|
||||
extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
|
||||
extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
|
||||
extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
|
||||
extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
|
||||
extern void ath5k_hw_set_associd(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
|
||||
/* Receive start/stop functions */
|
||||
extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
|
||||
@ -1329,17 +1315,21 @@ static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
|
||||
return turbo ? (clock / 80) : (clock / 40);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from a register
|
||||
*/
|
||||
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
|
||||
{
|
||||
return &ah->common;
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
|
||||
{
|
||||
return &(ath5k_hw_common(ah)->regulatory);
|
||||
}
|
||||
|
||||
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
|
||||
{
|
||||
return ioread32(ah->ah_iobase + reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to a register
|
||||
*/
|
||||
static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
|
||||
{
|
||||
iowrite32(val, ah->ah_iobase + reg);
|
||||
|
@ -101,25 +101,15 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
|
||||
* -ENODEV if the device is not supported or prints an error msg if something
|
||||
* else went wrong.
|
||||
*/
|
||||
struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
|
||||
int ath5k_hw_attach(struct ath5k_softc *sc)
|
||||
{
|
||||
struct ath5k_hw *ah;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
struct pci_dev *pdev = sc->pdev;
|
||||
struct ath5k_eeprom_info *ee;
|
||||
int ret;
|
||||
u32 srev;
|
||||
|
||||
/*If we passed the test malloc a ath5k_hw struct*/
|
||||
ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
|
||||
if (ah == NULL) {
|
||||
ret = -ENOMEM;
|
||||
ATH5K_ERR(sc, "out of memory\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ah->ah_sc = sc;
|
||||
ah->ah_iobase = sc->iobase;
|
||||
|
||||
/*
|
||||
* HW information
|
||||
*/
|
||||
@ -278,12 +268,12 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ee = &ah->ah_capabilities.cap_eeprom;
|
||||
|
||||
/*
|
||||
* Write PCI-E power save settings
|
||||
*/
|
||||
if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
|
||||
ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
|
||||
ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
|
||||
|
||||
@ -321,7 +311,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
|
||||
}
|
||||
|
||||
/* Crypto settings */
|
||||
ee = &ah->ah_capabilities.cap_eeprom;
|
||||
ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 &&
|
||||
(ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
|
||||
!AR5K_EEPROM_AES_DIS(ee->ee_misc5));
|
||||
@ -336,8 +325,8 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
|
||||
ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
|
||||
|
||||
/* 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);
|
||||
memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
|
||||
ath5k_hw_set_associd(ah);
|
||||
ath5k_hw_set_opmode(ah);
|
||||
|
||||
ath5k_hw_rfgain_opt_init(ah);
|
||||
@ -345,11 +334,10 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
|
||||
/* turn on HW LEDs */
|
||||
ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
|
||||
|
||||
return ah;
|
||||
return 0;
|
||||
err_free:
|
||||
kfree(ah);
|
||||
err:
|
||||
return ERR_PTR(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,5 +357,4 @@ void ath5k_hw_detach(struct ath5k_hw *ah)
|
||||
ath5k_eeprom_detach(ah);
|
||||
|
||||
/* assume interrupts are down */
|
||||
kfree(ah);
|
||||
}
|
||||
|
@ -195,12 +195,13 @@ static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id);
|
||||
static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
|
||||
#ifdef CONFIG_PM
|
||||
static int ath5k_pci_suspend(struct pci_dev *pdev,
|
||||
pm_message_t state);
|
||||
static int ath5k_pci_resume(struct pci_dev *pdev);
|
||||
static int ath5k_pci_suspend(struct device *dev);
|
||||
static int ath5k_pci_resume(struct device *dev);
|
||||
|
||||
SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
|
||||
#define ATH5K_PM_OPS (&ath5k_pm_ops)
|
||||
#else
|
||||
#define ath5k_pci_suspend NULL
|
||||
#define ath5k_pci_resume NULL
|
||||
#define ATH5K_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct pci_driver ath5k_pci_driver = {
|
||||
@ -208,8 +209,7 @@ static struct pci_driver ath5k_pci_driver = {
|
||||
.id_table = ath5k_pci_id_table,
|
||||
.probe = ath5k_pci_probe,
|
||||
.remove = __devexit_p(ath5k_pci_remove),
|
||||
.suspend = ath5k_pci_suspend,
|
||||
.resume = ath5k_pci_resume,
|
||||
.driver.pm = ATH5K_PM_OPS,
|
||||
};
|
||||
|
||||
|
||||
@ -437,6 +437,22 @@ ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
|
||||
|
||||
return name;
|
||||
}
|
||||
static unsigned int ath5k_ioread32(void *hw_priv, u32 reg_offset)
|
||||
{
|
||||
struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv;
|
||||
return ath5k_hw_reg_read(ah, reg_offset);
|
||||
}
|
||||
|
||||
static void ath5k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
|
||||
{
|
||||
struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv;
|
||||
ath5k_hw_reg_write(ah, val, reg_offset);
|
||||
}
|
||||
|
||||
static const struct ath_ops ath5k_common_ops = {
|
||||
.read = ath5k_ioread32,
|
||||
.write = ath5k_iowrite32,
|
||||
};
|
||||
|
||||
static int __devinit
|
||||
ath5k_pci_probe(struct pci_dev *pdev,
|
||||
@ -444,6 +460,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
||||
{
|
||||
void __iomem *mem;
|
||||
struct ath5k_softc *sc;
|
||||
struct ath_common *common;
|
||||
struct ieee80211_hw *hw;
|
||||
int ret;
|
||||
u8 csz;
|
||||
@ -547,7 +564,6 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
||||
__set_bit(ATH_STAT_INVALID, sc->status);
|
||||
|
||||
sc->iobase = mem; /* So we can unmap it on detach */
|
||||
sc->common.cachelsz = csz << 2; /* convert to bytes */
|
||||
sc->opmode = NL80211_IFTYPE_STATION;
|
||||
sc->bintval = 1000;
|
||||
mutex_init(&sc->lock);
|
||||
@ -565,13 +581,28 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* Initialize device */
|
||||
sc->ah = ath5k_hw_attach(sc);
|
||||
if (IS_ERR(sc->ah)) {
|
||||
ret = PTR_ERR(sc->ah);
|
||||
/*If we passed the test malloc a ath5k_hw struct*/
|
||||
sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
|
||||
if (!sc->ah) {
|
||||
ret = -ENOMEM;
|
||||
ATH5K_ERR(sc, "out of memory\n");
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
sc->ah->ah_sc = sc;
|
||||
sc->ah->ah_iobase = sc->iobase;
|
||||
common = ath5k_hw_common(sc->ah);
|
||||
common->ops = &ath5k_common_ops;
|
||||
common->ah = sc->ah;
|
||||
common->hw = hw;
|
||||
common->cachelsz = csz << 2; /* convert to bytes */
|
||||
|
||||
/* Initialize device */
|
||||
ret = ath5k_hw_attach(sc);
|
||||
if (ret) {
|
||||
goto err_free_ah;
|
||||
}
|
||||
|
||||
/* set up multi-rate retry capabilities */
|
||||
if (sc->ah->ah_version == AR5K_AR5212) {
|
||||
hw->max_rates = 4;
|
||||
@ -640,6 +671,8 @@ err_ah:
|
||||
ath5k_hw_detach(sc->ah);
|
||||
err_irq:
|
||||
free_irq(pdev->irq, sc);
|
||||
err_free_ah:
|
||||
kfree(sc->ah);
|
||||
err_free:
|
||||
ieee80211_free_hw(hw);
|
||||
err_map:
|
||||
@ -661,6 +694,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
|
||||
ath5k_debug_finish_device(sc);
|
||||
ath5k_detach(pdev, hw);
|
||||
ath5k_hw_detach(sc->ah);
|
||||
kfree(sc->ah);
|
||||
free_irq(pdev->irq, sc);
|
||||
pci_iounmap(pdev, sc->iobase);
|
||||
pci_release_region(pdev, 0);
|
||||
@ -669,33 +703,20 @@ ath5k_pci_remove(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int
|
||||
ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int ath5k_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
|
||||
ath5k_led_off(sc);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_pci_resume(struct pci_dev *pdev)
|
||||
static int ath5k_pci_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
int err;
|
||||
|
||||
pci_restore_state(pdev);
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Suspend/Resume resets the PCI configuration space, so we have to
|
||||
@ -718,7 +739,7 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath_regulatory *regulatory = &sc->common.regulatory;
|
||||
struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah);
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request, regulatory);
|
||||
}
|
||||
@ -728,7 +749,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath_regulatory *regulatory = &sc->common.regulatory;
|
||||
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
|
||||
u8 mac[ETH_ALEN] = {};
|
||||
int ret;
|
||||
|
||||
@ -815,7 +836,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
|
||||
SET_IEEE80211_PERM_ADDR(hw, mac);
|
||||
/* All MAC address bits matter for ACKs */
|
||||
memset(sc->bssidmask, 0xff, ETH_ALEN);
|
||||
memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
|
||||
ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
|
||||
|
||||
regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
|
||||
@ -1153,19 +1174,20 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
|
||||
static
|
||||
struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(sc->ah);
|
||||
struct sk_buff *skb;
|
||||
|
||||
/*
|
||||
* Allocate buffer with headroom_needed space for the
|
||||
* fake physical layer header at the start.
|
||||
*/
|
||||
skb = ath_rxbuf_alloc(&sc->common,
|
||||
sc->rxbufsize + sc->common.cachelsz - 1,
|
||||
skb = ath_rxbuf_alloc(common,
|
||||
sc->rxbufsize + common->cachelsz - 1,
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (!skb) {
|
||||
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
|
||||
sc->rxbufsize + sc->common.cachelsz - 1);
|
||||
sc->rxbufsize + common->cachelsz - 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1606,13 +1628,14 @@ static int
|
||||
ath5k_rx_start(struct ath5k_softc *sc)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
struct ath5k_buf *bf;
|
||||
int ret;
|
||||
|
||||
sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
|
||||
sc->rxbufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
|
||||
sc->common.cachelsz, sc->rxbufsize);
|
||||
common->cachelsz, sc->rxbufsize);
|
||||
|
||||
spin_lock_bh(&sc->rxbuflock);
|
||||
sc->rxlink = NULL;
|
||||
@ -1685,13 +1708,14 @@ static void
|
||||
ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
|
||||
struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(sc->ah);
|
||||
u64 tsf, bc_tstamp;
|
||||
u32 hw_tu;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
|
||||
if (ieee80211_is_beacon(mgmt->frame_control) &&
|
||||
le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
|
||||
memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
|
||||
memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) == 0) {
|
||||
/*
|
||||
* Received an IBSS beacon with the same BSSID. Hardware *must*
|
||||
* have updated the local TSF. We have to work around various
|
||||
@ -3177,6 +3201,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
@ -3185,10 +3210,9 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
|
||||
if (changes & BSS_CHANGED_BSSID) {
|
||||
/* Cache for later use during resets */
|
||||
memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN);
|
||||
/* XXX: assoc id is set to 0 for now, mac80211 doesn't have
|
||||
* a clean way of letting us retrieve this yet. */
|
||||
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
|
||||
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
|
||||
common->curaid = 0;
|
||||
ath5k_hw_set_associd(ah);
|
||||
mmiowb();
|
||||
}
|
||||
|
||||
@ -3201,6 +3225,14 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
set_beacon_filter(hw, sc->assoc);
|
||||
ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
|
||||
AR5K_LED_ASSOC : AR5K_LED_INIT);
|
||||
if (bss_conf->assoc) {
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
|
||||
"Bss Info ASSOC %d, bssid: %pM\n",
|
||||
bss_conf->aid, common->curbssid);
|
||||
common->curaid = bss_conf->aid;
|
||||
ath5k_hw_set_associd(ah);
|
||||
/* Once ANI is available you would start it here */
|
||||
}
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON) {
|
||||
|
@ -115,7 +115,6 @@ struct ath5k_rfkill {
|
||||
* associated with an instance of a device */
|
||||
struct ath5k_softc {
|
||||
struct pci_dev *pdev; /* for dma mapping */
|
||||
struct ath_common common;
|
||||
void __iomem *iobase; /* address of the device */
|
||||
struct mutex lock; /* dev-level lock */
|
||||
struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES];
|
||||
@ -202,15 +201,4 @@ struct ath5k_softc {
|
||||
#define ath5k_hw_hasveol(_ah) \
|
||||
(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
|
||||
|
||||
static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
|
||||
{
|
||||
return &ah->ah_sc->common;
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
|
||||
{
|
||||
return &(ath5k_hw_common(ah)->regulatory);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -560,8 +560,8 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
|
||||
{ AR5K_SLEEP0, 0x0002aaaa },
|
||||
{ AR5K_SLEEP1, 0x02005555 },
|
||||
{ AR5K_SLEEP2, 0x00000000 },
|
||||
{ AR5K_BSS_IDM0, 0xffffffff },
|
||||
{ AR5K_BSS_IDM1, 0x0000ffff },
|
||||
{ AR_BSSMSKL, 0xffffffff },
|
||||
{ AR_BSSMSKU, 0x0000ffff },
|
||||
{ AR5K_TXPC, 0x00000000 },
|
||||
{ AR5K_PROFCNT_TX, 0x00000000 },
|
||||
{ AR5K_PROFCNT_RX, 0x00000000 },
|
||||
|
@ -24,6 +24,8 @@
|
||||
* Protocol Control Unit Functions *
|
||||
\*********************************/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "ath5k.h"
|
||||
#include "reg.h"
|
||||
#include "debug.h"
|
||||
@ -44,6 +46,7 @@
|
||||
*/
|
||||
int ath5k_hw_set_opmode(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
u32 pcu_reg, beacon_reg, low_id, high_id;
|
||||
|
||||
|
||||
@ -95,8 +98,8 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
|
||||
/*
|
||||
* Set PCU registers
|
||||
*/
|
||||
low_id = AR5K_LOW_ID(ah->ah_sta_id);
|
||||
high_id = AR5K_HIGH_ID(ah->ah_sta_id);
|
||||
low_id = get_unaligned_le32(common->macaddr);
|
||||
high_id = get_unaligned_le16(common->macaddr + 4);
|
||||
ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
|
||||
ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
|
||||
|
||||
@ -238,28 +241,6 @@ int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************\
|
||||
* BSSID handling *
|
||||
\****************/
|
||||
|
||||
/**
|
||||
* ath5k_hw_get_lladdr - Get station id
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @mac: The card's mac address
|
||||
*
|
||||
* Initialize ah->ah_sta_id using the mac address provided
|
||||
* (just a memcpy).
|
||||
*
|
||||
* TODO: Remove it once we merge ath5k_softc and ath5k_hw
|
||||
*/
|
||||
void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
memcpy(mac, ah->ah_sta_id, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_set_lladdr - Set station id
|
||||
*
|
||||
@ -270,17 +251,18 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
|
||||
*/
|
||||
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
u32 low_id, high_id;
|
||||
u32 pcu_reg;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/* Set new station ID */
|
||||
memcpy(ah->ah_sta_id, mac, ETH_ALEN);
|
||||
memcpy(common->macaddr, mac, ETH_ALEN);
|
||||
|
||||
pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
|
||||
|
||||
low_id = AR5K_LOW_ID(mac);
|
||||
high_id = AR5K_HIGH_ID(mac);
|
||||
low_id = get_unaligned_le32(mac);
|
||||
high_id = get_unaligned_le16(mac + 4);
|
||||
|
||||
ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
|
||||
ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
|
||||
@ -297,159 +279,51 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
|
||||
*
|
||||
* Sets the BSSID which trigers the "SME Join" operation
|
||||
*/
|
||||
void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
|
||||
void ath5k_hw_set_associd(struct ath5k_hw *ah)
|
||||
{
|
||||
u32 low_id, high_id;
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
u16 tim_offset = 0;
|
||||
|
||||
/*
|
||||
* Set simple BSSID mask on 5212
|
||||
*/
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
|
||||
AR5K_BSS_IDM0);
|
||||
ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
|
||||
AR5K_BSS_IDM1);
|
||||
}
|
||||
if (ah->ah_version == AR5K_AR5212)
|
||||
ath_hw_setbssidmask(common);
|
||||
|
||||
/*
|
||||
* Set BSSID which triggers the "SME Join" operation
|
||||
*/
|
||||
low_id = AR5K_LOW_ID(bssid);
|
||||
high_id = AR5K_HIGH_ID(bssid);
|
||||
ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
|
||||
ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
|
||||
AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
|
||||
ath5k_hw_reg_write(ah,
|
||||
get_unaligned_le32(common->curbssid),
|
||||
AR5K_BSS_ID0);
|
||||
ath5k_hw_reg_write(ah,
|
||||
get_unaligned_le16(common->curbssid + 4) |
|
||||
((common->curaid & 0x3fff) << AR5K_BSS_ID1_AID_S),
|
||||
AR5K_BSS_ID1);
|
||||
|
||||
if (assoc_id == 0) {
|
||||
if (common->curaid == 0) {
|
||||
ath5k_hw_disable_pspoll(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
|
||||
tim_offset ? tim_offset + 4 : 0);
|
||||
tim_offset ? tim_offset + 4 : 0);
|
||||
|
||||
ath5k_hw_enable_pspoll(ah, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_set_bssid_mask - filter out bssids we listen
|
||||
*
|
||||
* @ah: the &struct ath5k_hw
|
||||
* @mask: the bssid_mask, a u8 array of size ETH_ALEN
|
||||
*
|
||||
* BSSID masking is a method used by AR5212 and newer hardware to inform PCU
|
||||
* which bits of the interface's MAC address should be looked at when trying
|
||||
* to decide which packets to ACK. In station mode and AP mode with a single
|
||||
* BSS every bit matters since we lock to only one BSS. In AP mode with
|
||||
* multiple BSSes (virtual interfaces) not every bit matters because hw must
|
||||
* accept frames for all BSSes and so we tweak some bits of our mac address
|
||||
* in order to have multiple BSSes.
|
||||
*
|
||||
* NOTE: This is a simple filter and does *not* filter out all
|
||||
* relevant frames. Some frames that are not for us might get ACKed from us
|
||||
* by PCU because they just match the mask.
|
||||
*
|
||||
* When handling multiple BSSes you can get the BSSID mask by computing the
|
||||
* set of ~ ( MAC XOR BSSID ) for all bssids we handle.
|
||||
*
|
||||
* When you do this you are essentially computing the common bits of all your
|
||||
* BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
|
||||
* the MAC address to obtain the relevant bits and compare the result with
|
||||
* (frame's BSSID & mask) to see if they match.
|
||||
*/
|
||||
/*
|
||||
* Simple example: on your card you have have two BSSes you have created with
|
||||
* BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
|
||||
* There is another BSSID-03 but you are not part of it. For simplicity's sake,
|
||||
* assuming only 4 bits for a mac address and for BSSIDs you can then have:
|
||||
*
|
||||
* \
|
||||
* MAC: 0001 |
|
||||
* BSSID-01: 0100 | --> Belongs to us
|
||||
* BSSID-02: 1001 |
|
||||
* /
|
||||
* -------------------
|
||||
* BSSID-03: 0110 | --> External
|
||||
* -------------------
|
||||
*
|
||||
* Our bssid_mask would then be:
|
||||
*
|
||||
* On loop iteration for BSSID-01:
|
||||
* ~(0001 ^ 0100) -> ~(0101)
|
||||
* -> 1010
|
||||
* bssid_mask = 1010
|
||||
*
|
||||
* On loop iteration for BSSID-02:
|
||||
* bssid_mask &= ~(0001 ^ 1001)
|
||||
* bssid_mask = (1010) & ~(0001 ^ 1001)
|
||||
* bssid_mask = (1010) & ~(1001)
|
||||
* bssid_mask = (1010) & (0110)
|
||||
* bssid_mask = 0010
|
||||
*
|
||||
* A bssid_mask of 0010 means "only pay attention to the second least
|
||||
* significant bit". This is because its the only bit common
|
||||
* amongst the MAC and all BSSIDs we support. To findout what the real
|
||||
* common bit is we can simply "&" the bssid_mask now with any BSSID we have
|
||||
* or our MAC address (we assume the hardware uses the MAC address).
|
||||
*
|
||||
* Now, suppose there's an incoming frame for BSSID-03:
|
||||
*
|
||||
* IFRAME-01: 0110
|
||||
*
|
||||
* An easy eye-inspeciton of this already should tell you that this frame
|
||||
* will not pass our check. This is beacuse the bssid_mask tells the
|
||||
* hardware to only look at the second least significant bit and the
|
||||
* common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
|
||||
* as 1, which does not match 0.
|
||||
*
|
||||
* So with IFRAME-01 we *assume* the hardware will do:
|
||||
*
|
||||
* allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
||||
* --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
|
||||
* --> allow = (0010) == 0000 ? 1 : 0;
|
||||
* --> allow = 0
|
||||
*
|
||||
* Lets now test a frame that should work:
|
||||
*
|
||||
* IFRAME-02: 0001 (we should allow)
|
||||
*
|
||||
* allow = (0001 & 1010) == 1010
|
||||
*
|
||||
* allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
||||
* --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
|
||||
* --> allow = (0010) == (0010)
|
||||
* --> allow = 1
|
||||
*
|
||||
* Other examples:
|
||||
*
|
||||
* IFRAME-03: 0100 --> allowed
|
||||
* IFRAME-04: 1001 --> allowed
|
||||
* IFRAME-05: 1101 --> allowed but its not for us!!!
|
||||
*
|
||||
*/
|
||||
int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
|
||||
void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
|
||||
{
|
||||
u32 low_id, high_id;
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/* Cache bssid mask so that we can restore it
|
||||
* on reset */
|
||||
memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
low_id = AR5K_LOW_ID(mask);
|
||||
high_id = AR5K_HIGH_ID(mask);
|
||||
|
||||
ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
|
||||
ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
memcpy(common->bssidmask, mask, ETH_ALEN);
|
||||
if (ah->ah_version == AR5K_AR5212)
|
||||
ath_hw_setbssidmask(common);
|
||||
}
|
||||
|
||||
|
||||
/************\
|
||||
* RX Control *
|
||||
\************/
|
||||
@ -1157,14 +1031,17 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
|
||||
/* Invalid entry (key table overflow) */
|
||||
AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
||||
|
||||
/* MAC may be NULL if it's a broadcast key. In this case no need to
|
||||
* to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
|
||||
/*
|
||||
* MAC may be NULL if it's a broadcast key. In this case no need to
|
||||
* to compute get_unaligned_le32 and get_unaligned_le16 as we
|
||||
* already know it.
|
||||
*/
|
||||
if (!mac) {
|
||||
low_id = 0xffffffff;
|
||||
high_id = 0xffff | AR5K_KEYTABLE_VALID;
|
||||
} else {
|
||||
low_id = AR5K_LOW_ID(mac);
|
||||
high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
|
||||
low_id = get_unaligned_le32(mac);
|
||||
high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID;
|
||||
}
|
||||
|
||||
ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
|
||||
|
@ -35,7 +35,7 @@
|
||||
* released by Atheros and on various debug messages found on the net.
|
||||
*/
|
||||
|
||||
|
||||
#include "../reg.h"
|
||||
|
||||
/*====MAC DMA REGISTERS====*/
|
||||
|
||||
@ -1649,12 +1649,6 @@
|
||||
#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */
|
||||
#define AR5K_SLEEP2_DTIM_PER_S 16
|
||||
|
||||
/*
|
||||
* BSSID mask registers
|
||||
*/
|
||||
#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */
|
||||
#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */
|
||||
|
||||
/*
|
||||
* TX power control (TPC) register
|
||||
*
|
||||
|
@ -25,6 +25,8 @@
|
||||
Reset functions and helpers
|
||||
\*****************************/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <linux/pci.h> /* To determine if a card is pci-e */
|
||||
#include <linux/log2.h>
|
||||
#include "ath5k.h"
|
||||
@ -870,6 +872,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
||||
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
||||
struct ieee80211_channel *channel, bool change_channel)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
|
||||
u32 phy_tst1;
|
||||
u8 mode, freq, ee_mode, ant[2];
|
||||
@ -1171,10 +1174,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
||||
ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
|
||||
|
||||
/* Restore sta_id flags and preserve our mac address*/
|
||||
ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
|
||||
AR5K_STA_ID0);
|
||||
ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
|
||||
AR5K_STA_ID1);
|
||||
ath5k_hw_reg_write(ah,
|
||||
get_unaligned_le32(common->macaddr),
|
||||
AR5K_STA_ID0);
|
||||
ath5k_hw_reg_write(ah,
|
||||
staid1_flags | get_unaligned_le16(common->macaddr + 4),
|
||||
AR5K_STA_ID1);
|
||||
|
||||
|
||||
/*
|
||||
@ -1182,8 +1187,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
||||
*/
|
||||
|
||||
/* Restore bssid and bssid mask */
|
||||
/* XXX: add ah->aid once mac80211 gives this to us */
|
||||
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
|
||||
ath5k_hw_set_associd(ah);
|
||||
|
||||
/* Set PCU config */
|
||||
ath5k_hw_set_opmode(ah);
|
||||
|
@ -1,6 +1,10 @@
|
||||
config ATH9K_HW
|
||||
tristate
|
||||
|
||||
config ATH9K
|
||||
tristate "Atheros 802.11n wireless cards support"
|
||||
depends on PCI && MAC80211 && WLAN_80211
|
||||
select ATH9K_HW
|
||||
select MAC80211_LEDS
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
@ -16,6 +20,8 @@ config ATH9K
|
||||
|
||||
If you choose to build a module, it'll be called ath9k.
|
||||
|
||||
if ATH_DEBUG
|
||||
|
||||
config ATH9K_DEBUG
|
||||
bool "Atheros ath9k debugging"
|
||||
depends on ATH9K
|
||||
@ -26,3 +32,5 @@ config ATH9K_DEBUG
|
||||
modprobe ath9k debug=0x00000200
|
||||
|
||||
Look in ath9k/debug.h for possible debug masks
|
||||
|
||||
endif # ATH_DEBUG
|
||||
|
@ -1,22 +1,25 @@
|
||||
ath9k-y += hw.o \
|
||||
eeprom.o \
|
||||
eeprom_def.o \
|
||||
eeprom_4k.o \
|
||||
eeprom_9287.o \
|
||||
mac.o \
|
||||
calib.o \
|
||||
ani.o \
|
||||
phy.o \
|
||||
beacon.o \
|
||||
ath9k-y += beacon.o \
|
||||
main.o \
|
||||
recv.o \
|
||||
xmit.o \
|
||||
virtual.o \
|
||||
rc.o \
|
||||
btcoex.o
|
||||
rc.o
|
||||
|
||||
ath9k-$(CONFIG_PCI) += pci.o
|
||||
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
|
||||
ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
|
||||
|
||||
obj-$(CONFIG_ATH9K) += ath9k.o
|
||||
|
||||
ath9k_hw-y:= hw.o \
|
||||
eeprom.o \
|
||||
eeprom_def.o \
|
||||
eeprom_4k.o \
|
||||
eeprom_9287.o \
|
||||
calib.o \
|
||||
ani.o \
|
||||
phy.o \
|
||||
btcoex.o \
|
||||
mac.o \
|
||||
|
||||
obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
|
||||
|
@ -22,27 +22,31 @@
|
||||
#include "ath9k.h"
|
||||
|
||||
/* return bus cachesize in 4B word units */
|
||||
static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
|
||||
{
|
||||
*csz = L1_CACHE_BYTES >> 2;
|
||||
}
|
||||
|
||||
static void ath_ahb_cleanup(struct ath_softc *sc)
|
||||
static void ath_ahb_cleanup(struct ath_common *common)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
struct ath_softc *sc = ah->ah_sc;
|
||||
iounmap(sc->mem);
|
||||
}
|
||||
|
||||
static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||
static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
struct ath_softc *sc = ah->ah_sc;
|
||||
struct platform_device *pdev = to_platform_device(sc->dev);
|
||||
struct ath9k_platform_data *pdata;
|
||||
|
||||
pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
|
||||
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"%s: flash read failed, offset %08x is out of range\n",
|
||||
__func__, off);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"%s: flash read failed, offset %08x "
|
||||
"is out of range\n",
|
||||
__func__, off);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -116,10 +120,9 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
sc->hw = hw;
|
||||
sc->dev = &pdev->dev;
|
||||
sc->mem = mem;
|
||||
sc->bus_ops = &ath_ahb_bus_ops;
|
||||
sc->irq = irq;
|
||||
|
||||
ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0);
|
||||
ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize device\n");
|
||||
goto err_free_hw;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
@ -31,8 +31,8 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"No more channel states left. Using channel 0\n");
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
|
||||
"No more channel states left. Using channel 0\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -41,16 +41,17 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah,
|
||||
enum ath9k_ani_cmd cmd, int param)
|
||||
{
|
||||
struct ar5416AniState *aniState = ah->curani;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
switch (cmd & ah->ani_function) {
|
||||
case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"level out of range (%u > %u)\n",
|
||||
level,
|
||||
(unsigned)ARRAY_SIZE(ah->totalSizeDesired));
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"level out of range (%u > %u)\n",
|
||||
level,
|
||||
(unsigned)ARRAY_SIZE(ah->totalSizeDesired));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -152,10 +153,10 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah,
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(firstep)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"level out of range (%u > %u)\n",
|
||||
level,
|
||||
(unsigned) ARRAY_SIZE(firstep));
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"level out of range (%u > %u)\n",
|
||||
level,
|
||||
(unsigned) ARRAY_SIZE(firstep));
|
||||
return false;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
|
||||
@ -174,11 +175,10 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah,
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(cycpwrThr1)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"level out of range (%u > %u)\n",
|
||||
level,
|
||||
(unsigned)
|
||||
ARRAY_SIZE(cycpwrThr1));
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"level out of range (%u > %u)\n",
|
||||
level,
|
||||
(unsigned) ARRAY_SIZE(cycpwrThr1));
|
||||
return false;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
|
||||
@ -194,25 +194,28 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah,
|
||||
case ATH9K_ANI_PRESENT:
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"invalid cmd %u\n", cmd);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"invalid cmd %u\n", cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n");
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
|
||||
"ofdmWeakSigDetectOff=%d\n",
|
||||
aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"cckWeakSigThreshold=%d, "
|
||||
"firstepLevel=%d, listenTime=%d\n",
|
||||
aniState->cckWeakSigThreshold, aniState->firstepLevel,
|
||||
aniState->listenTime);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
|
||||
"ofdmWeakSigDetectOff=%d\n",
|
||||
aniState->noiseImmunityLevel,
|
||||
aniState->spurImmunityLevel,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"cckWeakSigThreshold=%d, "
|
||||
"firstepLevel=%d, listenTime=%d\n",
|
||||
aniState->cckWeakSigThreshold,
|
||||
aniState->firstepLevel,
|
||||
aniState->listenTime);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
|
||||
aniState->cycleCount, aniState->ofdmPhyErrCount,
|
||||
aniState->cycleCount,
|
||||
aniState->ofdmPhyErrCount,
|
||||
aniState->cckPhyErrCount);
|
||||
|
||||
return true;
|
||||
@ -231,6 +234,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
|
||||
static void ath9k_ani_restart(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
@ -240,24 +244,24 @@ static void ath9k_ani_restart(struct ath_hw *ah)
|
||||
|
||||
if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
|
||||
aniState->ofdmPhyErrBase = 0;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"OFDM Trigger is too high for hw counters\n");
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"OFDM Trigger is too high for hw counters\n");
|
||||
} else {
|
||||
aniState->ofdmPhyErrBase =
|
||||
AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
|
||||
}
|
||||
if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
|
||||
aniState->cckPhyErrBase = 0;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"CCK Trigger is too high for hw counters\n");
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"CCK Trigger is too high for hw counters\n");
|
||||
} else {
|
||||
aniState->cckPhyErrBase =
|
||||
AR_PHY_COUNTMAX - aniState->cckTrigHigh;
|
||||
}
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Writing ofdmbase=%u cckbase=%u\n",
|
||||
aniState->ofdmPhyErrBase,
|
||||
aniState->cckPhyErrBase);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Writing ofdmbase=%u cckbase=%u\n",
|
||||
aniState->ofdmPhyErrBase,
|
||||
aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
@ -271,7 +275,7 @@ static void ath9k_ani_restart(struct ath_hw *ah)
|
||||
|
||||
static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
@ -343,7 +347,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
|
||||
|
||||
static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
@ -464,6 +468,7 @@ void ath9k_ani_reset(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int index;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
@ -475,8 +480,8 @@ void ath9k_ani_reset(struct ath_hw *ah)
|
||||
|
||||
if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
|
||||
&& ah->opmode != NL80211_IFTYPE_ADHOC) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Reset ANI state opmode %u\n", ah->opmode);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Reset ANI state opmode %u\n", ah->opmode);
|
||||
ah->stats.ast_ani_reset++;
|
||||
|
||||
if (ah->opmode == NL80211_IFTYPE_AP) {
|
||||
@ -543,6 +548,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int32_t listenTime;
|
||||
u32 phyCnt1, phyCnt2;
|
||||
u32 ofdmPhyErrCnt, cckPhyErrCnt;
|
||||
@ -569,20 +575,22 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
|
||||
if (phyCnt1 < aniState->ofdmPhyErrBase ||
|
||||
phyCnt2 < aniState->cckPhyErrBase) {
|
||||
if (phyCnt1 < aniState->ofdmPhyErrBase) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"phyCnt1 0x%x, resetting "
|
||||
"counter value to 0x%x\n",
|
||||
phyCnt1, aniState->ofdmPhyErrBase);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"phyCnt1 0x%x, resetting "
|
||||
"counter value to 0x%x\n",
|
||||
phyCnt1,
|
||||
aniState->ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1,
|
||||
aniState->ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
|
||||
AR_PHY_ERR_OFDM_TIMING);
|
||||
}
|
||||
if (phyCnt2 < aniState->cckPhyErrBase) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"phyCnt2 0x%x, resetting "
|
||||
"counter value to 0x%x\n",
|
||||
phyCnt2, aniState->cckPhyErrBase);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"phyCnt2 0x%x, resetting "
|
||||
"counter value to 0x%x\n",
|
||||
phyCnt2,
|
||||
aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2,
|
||||
aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
|
||||
@ -621,10 +629,13 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_ani_monitor);
|
||||
|
||||
void ath9k_enable_mib_counters(struct ath_hw *ah)
|
||||
{
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
|
||||
|
||||
@ -640,7 +651,10 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
|
||||
/* Freeze the MIB counters, get the stats and then clear them */
|
||||
void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
|
||||
{
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
|
||||
|
||||
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
|
||||
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
|
||||
REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
|
||||
@ -653,6 +667,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
|
||||
u32 *rxf_pcnt,
|
||||
u32 *txf_pcnt)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
static u32 cycles, rx_clear, rx_frame, tx_frame;
|
||||
u32 good = 1;
|
||||
|
||||
@ -662,8 +677,8 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
|
||||
u32 cc = REG_READ(ah, AR_CCCNT);
|
||||
|
||||
if (cycles == 0 || cycles > cc) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"cycle counter wrap. ExtBusy = 0\n");
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"cycle counter wrap. ExtBusy = 0\n");
|
||||
good = 0;
|
||||
} else {
|
||||
u32 cc_d = cc - cycles;
|
||||
@ -742,6 +757,7 @@ void ath9k_hw_procmibevent(struct ath_hw *ah)
|
||||
ath9k_ani_restart(ah);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_procmibevent);
|
||||
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah)
|
||||
{
|
||||
@ -762,9 +778,10 @@ void ath9k_hw_ani_setup(struct ath_hw *ah)
|
||||
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int i;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n");
|
||||
ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
|
||||
|
||||
memset(ah->ani, 0, sizeof(ah->ani));
|
||||
for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
|
||||
@ -786,11 +803,11 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Setting OfdmErrBase = 0x%08x\n",
|
||||
ah->ani[0].ofdmPhyErrBase);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
|
||||
ah->ani[0].cckPhyErrBase);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Setting OfdmErrBase = 0x%08x\n",
|
||||
ah->ani[0].ofdmPhyErrBase);
|
||||
ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
|
||||
ah->ani[0].cckPhyErrBase);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
|
||||
@ -803,7 +820,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
|
||||
void ath9k_hw_ani_disable(struct ath_hw *ah)
|
||||
{
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n");
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n");
|
||||
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, 0);
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "rc.h"
|
||||
#include "debug.h"
|
||||
#include "../ath.h"
|
||||
#include "btcoex.h"
|
||||
#include "../debug.h"
|
||||
|
||||
struct ath_node;
|
||||
|
||||
@ -54,15 +54,11 @@ struct ath_node;
|
||||
|
||||
#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define ASSERT(exp) BUG_ON(!(exp))
|
||||
|
||||
#define TSF_TO_TU(_h,_l) \
|
||||
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
|
||||
|
||||
#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
|
||||
|
||||
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
struct ath_config {
|
||||
u32 ath_aggr_prot;
|
||||
u16 txpowlimit;
|
||||
@ -191,7 +187,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
/* minimum h/w qdepth to be sustained to maximize aggregation */
|
||||
#define ATH_AGGR_MIN_QDEPTH 2
|
||||
#define ATH_AMPDU_SUBFRAME_DEFAULT 32
|
||||
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
|
||||
|
||||
#define IEEE80211_SEQ_SEQ_SHIFT 4
|
||||
#define IEEE80211_SEQ_MAX 4096
|
||||
@ -293,7 +288,6 @@ struct ath_tx_control {
|
||||
|
||||
#define ATH_RSSI_LPF_LEN 10
|
||||
#define RSSI_LPF_THRESHOLD -20
|
||||
#define ATH9K_RSSI_BAD 0x80
|
||||
#define ATH_RSSI_EP_MULTIPLIER (1<<7)
|
||||
#define ATH_EP_MUL(x, mul) ((x) * (mul))
|
||||
#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
|
||||
@ -427,7 +421,6 @@ struct ath_beacon {
|
||||
|
||||
void ath_beacon_tasklet(unsigned long data);
|
||||
void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
int ath_beaconq_setup(struct ath_hw *ah);
|
||||
int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
|
||||
void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
|
||||
|
||||
@ -451,6 +444,26 @@ struct ath_ani {
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
/* Defines the BT AR_BT_COEX_WGHT used */
|
||||
enum ath_stomp_type {
|
||||
ATH_BTCOEX_NO_STOMP,
|
||||
ATH_BTCOEX_STOMP_ALL,
|
||||
ATH_BTCOEX_STOMP_LOW,
|
||||
ATH_BTCOEX_STOMP_NONE
|
||||
};
|
||||
|
||||
struct ath_btcoex {
|
||||
bool hw_timer_enabled;
|
||||
spinlock_t btcoex_lock;
|
||||
struct timer_list period_timer; /* Timer for BT period */
|
||||
u32 bt_priority_cnt;
|
||||
unsigned long bt_priority_time;
|
||||
int bt_stomp_type; /* Types of BT stomping */
|
||||
u32 btcoex_no_stomp; /* in usec */
|
||||
u32 btcoex_period; /* in usec */
|
||||
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
|
||||
};
|
||||
|
||||
/********************/
|
||||
/* LED Control */
|
||||
/********************/
|
||||
@ -484,7 +497,6 @@ struct ath_led {
|
||||
* Used when PCI device not fully initialized by bootrom/BIOS
|
||||
*/
|
||||
#define DEFAULT_CACHELINE 32
|
||||
#define ATH_DEFAULT_NOISE_FLOOR -95
|
||||
#define ATH_REGCLASSIDS_MAX 10
|
||||
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
|
||||
#define ATH_MAX_SW_RETRIES 10
|
||||
@ -522,23 +534,14 @@ struct ath_led {
|
||||
#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
|
||||
#define SC_OP_WAIT_FOR_TX_ACK BIT(18)
|
||||
#define SC_OP_BEACON_SYNC BIT(19)
|
||||
#define SC_OP_BTCOEX_ENABLED BIT(20)
|
||||
#define SC_OP_BT_PRIORITY_DETECTED BIT(21)
|
||||
|
||||
struct ath_bus_ops {
|
||||
void (*read_cachesize)(struct ath_softc *sc, int *csz);
|
||||
void (*cleanup)(struct ath_softc *sc);
|
||||
bool (*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data);
|
||||
};
|
||||
|
||||
struct ath_wiphy;
|
||||
|
||||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
|
||||
struct ath_common common;
|
||||
|
||||
spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
|
||||
struct ath_wiphy *pri_wiphy;
|
||||
struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
|
||||
@ -565,24 +568,17 @@ struct ath_softc {
|
||||
spinlock_t sc_pm_lock;
|
||||
struct mutex mutex;
|
||||
|
||||
u8 curbssid[ETH_ALEN];
|
||||
u8 bssidmask[ETH_ALEN];
|
||||
u32 intrstatus;
|
||||
u32 sc_flags; /* SC_OP_* */
|
||||
u16 curtxpow;
|
||||
u16 curaid;
|
||||
u8 nbcnvifs;
|
||||
u16 nvifs;
|
||||
u8 tx_chainmask;
|
||||
u8 rx_chainmask;
|
||||
u32 keymax;
|
||||
DECLARE_BITMAP(keymap, ATH_KEYMAX);
|
||||
u8 splitmic;
|
||||
bool ps_enabled;
|
||||
unsigned long ps_usecount;
|
||||
enum ath9k_int imask;
|
||||
enum ath9k_ht_extprotspacing ht_extprotspacing;
|
||||
enum ath9k_ht_macmode tx_chan_width;
|
||||
|
||||
struct ath_config config;
|
||||
struct ath_rx rx;
|
||||
@ -609,10 +605,9 @@ struct ath_softc {
|
||||
#ifdef CONFIG_ATH9K_DEBUG
|
||||
struct ath9k_debug debug;
|
||||
#endif
|
||||
struct ath_bus_ops *bus_ops;
|
||||
struct ath_beacon_config cur_beacon_conf;
|
||||
struct delayed_work tx_complete_work;
|
||||
struct ath_btcoex_info btcoex_info;
|
||||
struct ath_btcoex btcoex;
|
||||
};
|
||||
|
||||
struct ath_wiphy {
|
||||
@ -634,31 +629,22 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
|
||||
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
|
||||
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
||||
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
||||
{
|
||||
return &ah->ah_sc->common;
|
||||
common->bus_ops->read_cachesize(common, csz);
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
|
||||
static inline void ath_bus_cleanup(struct ath_common *common)
|
||||
{
|
||||
return &(ath9k_hw_common(ah)->regulatory);
|
||||
}
|
||||
|
||||
static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
{
|
||||
sc->bus_ops->read_cachesize(sc, csz);
|
||||
}
|
||||
|
||||
static inline void ath_bus_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
sc->bus_ops->cleanup(sc);
|
||||
common->bus_ops->cleanup(common);
|
||||
}
|
||||
|
||||
extern struct ieee80211_ops ath9k_ops;
|
||||
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
void ath_cleanup(struct ath_softc *sc);
|
||||
int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid);
|
||||
int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops);
|
||||
void ath_detach(struct ath_softc *sc);
|
||||
const char *ath_mac_bb_name(u32 mac_bb_version);
|
||||
const char *ath_rf_name(u16 rf_version);
|
||||
@ -706,8 +692,5 @@ bool ath9k_wiphy_scanning(struct ath_softc *sc);
|
||||
void ath9k_wiphy_work(struct work_struct *work);
|
||||
bool ath9k_all_wiphys_idle(struct ath_softc *sc);
|
||||
|
||||
void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val);
|
||||
unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset);
|
||||
|
||||
int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
|
||||
#endif /* ATH9K_H */
|
||||
|
@ -26,6 +26,7 @@
|
||||
static int ath_beaconq_config(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_tx_queue_info qi;
|
||||
|
||||
ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
|
||||
@ -42,8 +43,8 @@ static int ath_beaconq_config(struct ath_softc *sc)
|
||||
}
|
||||
|
||||
if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to update h/w beacon queue parameters\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to update h/w beacon queue parameters\n");
|
||||
return 0;
|
||||
} else {
|
||||
ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
|
||||
@ -61,6 +62,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
|
||||
{
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_desc *ds;
|
||||
struct ath9k_11n_rate_series series[4];
|
||||
const struct ath_rate_table *rt;
|
||||
@ -108,7 +110,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
|
||||
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
|
||||
series[0].Tries = 1;
|
||||
series[0].Rate = rate;
|
||||
series[0].ChSel = sc->tx_chainmask;
|
||||
series[0].ChSel = common->tx_chainmask;
|
||||
series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
|
||||
ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
|
||||
series, 4, 0);
|
||||
@ -119,6 +121,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_buf *bf;
|
||||
struct ath_vif *avp;
|
||||
struct sk_buff *skb;
|
||||
@ -172,7 +175,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
|
||||
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"dma_mapping_error on beaconing\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -192,8 +196,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
|
||||
|
||||
if (skb && cabq_depth) {
|
||||
if (sc->nvifs > 1) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"Flushing previous cabq traffic\n");
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"Flushing previous cabq traffic\n");
|
||||
ath_draintxq(sc, cabq, false);
|
||||
}
|
||||
}
|
||||
@ -216,6 +220,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_buf *bf;
|
||||
struct ath_vif *avp;
|
||||
struct sk_buff *skb;
|
||||
@ -233,25 +238,14 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc,
|
||||
/* NB: caller is known to have already stopped tx dma */
|
||||
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
|
||||
ath9k_hw_txstart(ah, sc->beacon.beaconq);
|
||||
DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
|
||||
sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
|
||||
}
|
||||
|
||||
int ath_beaconq_setup(struct ath_hw *ah)
|
||||
{
|
||||
struct ath9k_tx_queue_info qi;
|
||||
|
||||
memset(&qi, 0, sizeof(qi));
|
||||
qi.tqi_aifs = 1;
|
||||
qi.tqi_cwmin = 0;
|
||||
qi.tqi_cwmax = 0;
|
||||
/* NB: don't enable any interrupts */
|
||||
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
|
||||
ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
|
||||
sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
|
||||
}
|
||||
|
||||
int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp;
|
||||
struct ath_buf *bf;
|
||||
struct sk_buff *skb;
|
||||
@ -309,7 +303,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
|
||||
/* NB: the beacon data buffer must be 32-bit aligned. */
|
||||
skb = ieee80211_beacon_get(sc->hw, vif);
|
||||
if (skb == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n");
|
||||
ath_print(common, ATH_DBG_BEACON, "cannot get skb\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -333,9 +327,10 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
|
||||
tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
|
||||
avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
|
||||
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"stagger beacons, bslot %d intval %u tsfadjust %llu\n",
|
||||
avp->av_bslot, intval, (unsigned long long)tsfadjust);
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"stagger beacons, bslot %d intval "
|
||||
"%u tsfadjust %llu\n",
|
||||
avp->av_bslot, intval, (unsigned long long)tsfadjust);
|
||||
|
||||
((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
|
||||
avp->tsf_adjust;
|
||||
@ -349,8 +344,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
|
||||
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"dma_mapping_error on beacon alloc\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"dma_mapping_error on beacon alloc\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -386,6 +381,7 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_buf *bf = NULL;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_wiphy *aphy;
|
||||
@ -405,12 +401,12 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
sc->beacon.bmisscnt++;
|
||||
|
||||
if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"missed %u consecutive beacons\n",
|
||||
sc->beacon.bmisscnt);
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"missed %u consecutive beacons\n",
|
||||
sc->beacon.bmisscnt);
|
||||
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"beacon is officially stuck\n");
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"beacon is officially stuck\n");
|
||||
sc->sc_flags |= SC_OP_TSF_RESET;
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
@ -419,9 +415,9 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
}
|
||||
|
||||
if (sc->beacon.bmisscnt != 0) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"resume beacon xmit after %u misses\n",
|
||||
sc->beacon.bmisscnt);
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"resume beacon xmit after %u misses\n",
|
||||
sc->beacon.bmisscnt);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
}
|
||||
|
||||
@ -447,9 +443,9 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
vif = sc->beacon.bslot[slot];
|
||||
aphy = sc->beacon.bslot_aphy[slot];
|
||||
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
|
||||
slot, tsf, tsftu, intval, vif);
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
|
||||
slot, tsf, tsftu, intval, vif);
|
||||
|
||||
bfaddr = 0;
|
||||
if (vif) {
|
||||
@ -490,7 +486,7 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
* are still pending on the queue.
|
||||
*/
|
||||
if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"beacon queue %u did not stop?\n", sc->beacon.beaconq);
|
||||
}
|
||||
|
||||
@ -502,6 +498,19 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_beacon_init(struct ath_softc *sc,
|
||||
u32 next_beacon,
|
||||
u32 beacon_period)
|
||||
{
|
||||
if (beacon_period & ATH9K_BEACON_RESET_TSF)
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period);
|
||||
|
||||
if (beacon_period & ATH9K_BEACON_RESET_TSF)
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* For multi-bss ap support beacons are either staggered evenly over N slots or
|
||||
* burst together. For the former arrange for the SWBA to be delivered for each
|
||||
@ -534,7 +543,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
|
||||
/* Set the computed AP beacon timers */
|
||||
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, 0);
|
||||
ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
|
||||
|
||||
@ -555,6 +564,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
|
||||
static void ath_beacon_config_sta(struct ath_softc *sc,
|
||||
struct ath_beacon_config *conf)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath9k_beacon_state bs;
|
||||
int dtimperiod, dtimcount, sleepduration;
|
||||
int cfpperiod, cfpcount;
|
||||
@ -651,11 +661,11 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
|
||||
/* TSF out of range threshold fixed at 1 second */
|
||||
bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
|
||||
bs.bs_bmissthreshold, bs.bs_sleepduration,
|
||||
bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
|
||||
ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
|
||||
bs.bs_bmissthreshold, bs.bs_sleepduration,
|
||||
bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
|
||||
|
||||
/* Set the computed STA beacon timers */
|
||||
|
||||
@ -669,6 +679,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
|
||||
struct ath_beacon_config *conf,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
u64 tsf;
|
||||
u32 tsftu, intval, nexttbtt;
|
||||
|
||||
@ -689,9 +700,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
|
||||
nexttbtt += intval;
|
||||
} while (nexttbtt < tsftu);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"IBSS nexttbtt %u intval %u (%u)\n",
|
||||
nexttbtt, intval, conf->beacon_interval);
|
||||
ath_print(common, ATH_DBG_BEACON,
|
||||
"IBSS nexttbtt %u intval %u (%u)\n",
|
||||
nexttbtt, intval, conf->beacon_interval);
|
||||
|
||||
/*
|
||||
* In IBSS mode enable the beacon timers but only enable SWBA interrupts
|
||||
@ -707,7 +718,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
|
||||
/* Set the computed ADHOC beacon timers */
|
||||
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, 0);
|
||||
ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
|
||||
|
||||
@ -719,6 +730,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
|
||||
void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
enum nl80211_iftype iftype;
|
||||
|
||||
/* Setup the beacon configuration parameters */
|
||||
@ -759,8 +771,8 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
ath_beacon_config_sta(sc, cur_conf);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"Unsupported beaconing mode\n");
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Unsupported beaconing mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,26 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static const struct ath_btcoex_config ath_bt_config = { 0, true, true,
|
||||
ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true };
|
||||
enum ath_bt_mode {
|
||||
ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */
|
||||
ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */
|
||||
ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */
|
||||
ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */
|
||||
};
|
||||
|
||||
struct ath_btcoex_config {
|
||||
u8 bt_time_extend;
|
||||
bool bt_txstate_extend;
|
||||
bool bt_txframe_extend;
|
||||
enum ath_bt_mode bt_mode; /* coexistence mode */
|
||||
bool bt_quiet_collision;
|
||||
bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/
|
||||
u8 bt_priority_time;
|
||||
u8 bt_first_slot_time;
|
||||
bool bt_hold_rx_clear;
|
||||
};
|
||||
|
||||
static const u16 ath_subsysid_tbl[] = {
|
||||
AR9280_COEX2WIRE_SUBSYSID,
|
||||
@ -29,141 +45,38 @@ static const u16 ath_subsysid_tbl[] = {
|
||||
* Checks the subsystem id of the device to see if it
|
||||
* supports btcoex
|
||||
*/
|
||||
bool ath_btcoex_supported(u16 subsysid)
|
||||
bool ath9k_hw_btcoex_supported(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!subsysid)
|
||||
if (!ah->hw_version.subsysid)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++)
|
||||
if (subsysid == ath_subsysid_tbl[i])
|
||||
if (ah->hw_version.subsysid == ath_subsysid_tbl[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detects if there is any priority bt traffic
|
||||
*/
|
||||
static void ath_detect_bt_priority(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
|
||||
|
||||
if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio))
|
||||
btinfo->bt_priority_cnt++;
|
||||
|
||||
if (time_after(jiffies, btinfo->bt_priority_time +
|
||||
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
|
||||
if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
|
||||
DPRINTF(sc, ATH_DBG_BTCOEX,
|
||||
"BT priority traffic detected");
|
||||
sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
|
||||
} else {
|
||||
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
|
||||
}
|
||||
|
||||
btinfo->bt_priority_cnt = 0;
|
||||
btinfo->bt_priority_time = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configures appropriate weight based on stomp type.
|
||||
*/
|
||||
static void ath_btcoex_bt_stomp(struct ath_softc *sc,
|
||||
struct ath_btcoex_info *btinfo,
|
||||
int stomp_type)
|
||||
{
|
||||
|
||||
switch (stomp_type) {
|
||||
case ATH_BTCOEX_STOMP_ALL:
|
||||
ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
|
||||
AR_STOMP_ALL_WLAN_WGHT);
|
||||
break;
|
||||
case ATH_BTCOEX_STOMP_LOW:
|
||||
ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
|
||||
AR_STOMP_LOW_WLAN_WGHT);
|
||||
break;
|
||||
case ATH_BTCOEX_STOMP_NONE:
|
||||
ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
|
||||
AR_STOMP_NONE_WLAN_WGHT);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ath9k_hw_btcoex_enable(sc->sc_ah);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the master bt coex timer which runs for every
|
||||
* 45ms, bt traffic will be given priority during 55% of this
|
||||
* period while wlan gets remaining 45%
|
||||
*/
|
||||
|
||||
static void ath_btcoex_period_timer(unsigned long data)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) data;
|
||||
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
|
||||
|
||||
ath_detect_bt_priority(sc);
|
||||
|
||||
spin_lock_bh(&btinfo->btcoex_lock);
|
||||
|
||||
ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
|
||||
|
||||
spin_unlock_bh(&btinfo->btcoex_lock);
|
||||
|
||||
if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) {
|
||||
if (btinfo->hw_timer_enabled)
|
||||
ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
|
||||
|
||||
ath_gen_timer_start(sc->sc_ah,
|
||||
btinfo->no_stomp_timer,
|
||||
(ath9k_hw_gettsf32(sc->sc_ah) +
|
||||
btinfo->btcoex_no_stomp),
|
||||
btinfo->btcoex_no_stomp * 10);
|
||||
btinfo->hw_timer_enabled = true;
|
||||
}
|
||||
|
||||
mod_timer(&btinfo->period_timer, jiffies +
|
||||
msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic tsf based hw timer which configures weight
|
||||
* registers to time slice between wlan and bt traffic
|
||||
*/
|
||||
|
||||
static void ath_btcoex_no_stomp_timer(void *arg)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)arg;
|
||||
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n");
|
||||
|
||||
spin_lock_bh(&btinfo->btcoex_lock);
|
||||
|
||||
if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
|
||||
ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
|
||||
else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
||||
ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
|
||||
|
||||
spin_unlock_bh(&btinfo->btcoex_lock);
|
||||
}
|
||||
|
||||
static int ath_init_btcoex_info(struct ath_hw *hw,
|
||||
struct ath_btcoex_info *btcoex_info)
|
||||
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
|
||||
{
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
const struct ath_btcoex_config ath_bt_config = {
|
||||
.bt_time_extend = 0,
|
||||
.bt_txstate_extend = true,
|
||||
.bt_txframe_extend = true,
|
||||
.bt_mode = ATH_BT_COEX_MODE_SLOTTED,
|
||||
.bt_quiet_collision = true,
|
||||
.bt_rxclear_polarity = true,
|
||||
.bt_priority_time = 2,
|
||||
.bt_first_slot_time = 5,
|
||||
.bt_hold_rx_clear = true,
|
||||
};
|
||||
u32 i;
|
||||
int qnum;
|
||||
|
||||
qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
|
||||
|
||||
btcoex_info->bt_coex_mode =
|
||||
(btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) |
|
||||
btcoex_hw->bt_coex_mode =
|
||||
(btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
|
||||
SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) |
|
||||
SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
|
||||
SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
|
||||
@ -174,167 +87,141 @@ static int ath_init_btcoex_info(struct ath_hw *hw,
|
||||
SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) |
|
||||
SM(qnum, AR_BT_QCU_THRESH);
|
||||
|
||||
btcoex_info->bt_coex_mode2 =
|
||||
btcoex_hw->bt_coex_mode2 =
|
||||
SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
|
||||
SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
|
||||
AR_BT_DISABLE_BT_ANT;
|
||||
|
||||
btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
|
||||
|
||||
btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
|
||||
|
||||
btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
|
||||
btcoex_info->btcoex_period / 100;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
|
||||
ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
|
||||
|
||||
setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer,
|
||||
(unsigned long) hw->ah_sc);
|
||||
void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw,
|
||||
ath_btcoex_no_stomp_timer,
|
||||
ath_btcoex_no_stomp_timer,
|
||||
(void *)hw->ah_sc, AR_FIRST_NDP_TIMER);
|
||||
/* connect bt_active to baseband */
|
||||
REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
|
||||
AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
|
||||
|
||||
if (btcoex_info->no_stomp_timer == NULL)
|
||||
return -ENOMEM;
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
|
||||
|
||||
spin_lock_init(&btcoex_info->btcoex_lock);
|
||||
/* Set input mux for bt_active to gpio pin */
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
|
||||
btcoex_hw->btactive_gpio);
|
||||
|
||||
return 0;
|
||||
/* Configure the desired gpio port for input */
|
||||
ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire);
|
||||
|
||||
void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
/* btcoex 3-wire */
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
|
||||
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
|
||||
|
||||
/* Set input mux for bt_prority_async and
|
||||
* bt_active_async to GPIO pins */
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
|
||||
btcoex_hw->btactive_gpio);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_PRIORITY,
|
||||
btcoex_hw->btpriority_gpio);
|
||||
|
||||
/* Configure the desired GPIO ports for input */
|
||||
|
||||
ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
|
||||
ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire);
|
||||
|
||||
static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
/* Configure the desired GPIO port for TX_FRAME output */
|
||||
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
|
||||
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
|
||||
}
|
||||
|
||||
int ath9k_hw_btcoex_init(struct ath_hw *ah)
|
||||
void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
|
||||
u32 bt_weight,
|
||||
u32 wlan_weight)
|
||||
{
|
||||
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
|
||||
int ret = 0;
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) {
|
||||
/* connect bt_active to baseband */
|
||||
REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
|
||||
AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
|
||||
btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
|
||||
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
|
||||
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
|
||||
static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
/* Set input mux for bt_active to gpio pin */
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
|
||||
btcoex_info->btactive_gpio);
|
||||
/*
|
||||
* Program coex mode and weight registers to
|
||||
* enable coex 3-wire
|
||||
*/
|
||||
REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode);
|
||||
REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights);
|
||||
REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2);
|
||||
|
||||
/* Configure the desired gpio port for input */
|
||||
ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
|
||||
} else {
|
||||
/* btcoex 3-wire */
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
|
||||
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
|
||||
REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
|
||||
REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
|
||||
|
||||
/* Set input mux for bt_prority_async and
|
||||
* bt_active_async to GPIO pins */
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
|
||||
btcoex_info->btactive_gpio);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_PRIORITY,
|
||||
btcoex_info->btpriority_gpio);
|
||||
|
||||
/* Configure the desired GPIO ports for input */
|
||||
|
||||
ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
|
||||
ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio);
|
||||
|
||||
ret = ath_init_btcoex_info(ah, btcoex_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
|
||||
AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
|
||||
}
|
||||
|
||||
void ath9k_hw_btcoex_enable(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) {
|
||||
/* Configure the desired GPIO port for TX_FRAME output */
|
||||
ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
|
||||
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
|
||||
} else {
|
||||
/*
|
||||
* Program coex mode and weight registers to
|
||||
* enable coex 3-wire
|
||||
*/
|
||||
REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode);
|
||||
REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights);
|
||||
REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_QUIET1,
|
||||
AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
|
||||
REG_RMW_FIELD(ah, AR_PCU_MISC,
|
||||
AR_PCU_BT_ANT_PREVENT_RX, 0);
|
||||
|
||||
ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
|
||||
AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
|
||||
switch (btcoex_hw->scheme) {
|
||||
case ATH_BTCOEX_CFG_NONE:
|
||||
break;
|
||||
case ATH_BTCOEX_CFG_2WIRE:
|
||||
ath9k_hw_btcoex_enable_2wire(ah);
|
||||
break;
|
||||
case ATH_BTCOEX_CFG_3WIRE:
|
||||
ath9k_hw_btcoex_enable_3wire(ah);
|
||||
break;
|
||||
}
|
||||
|
||||
REG_RMW(ah, AR_GPIO_PDPU,
|
||||
(0x2 << (btcoex_info->btactive_gpio * 2)),
|
||||
(0x3 << (btcoex_info->btactive_gpio * 2)));
|
||||
(0x2 << (btcoex_hw->btactive_gpio * 2)),
|
||||
(0x3 << (btcoex_hw->btactive_gpio * 2)));
|
||||
|
||||
ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED;
|
||||
ah->btcoex_hw.enabled = true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_btcoex_enable);
|
||||
|
||||
void ath9k_hw_btcoex_disable(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
|
||||
ath9k_hw_set_gpio(ah, btcoex_info->wlanactive_gpio, 0);
|
||||
ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
|
||||
|
||||
ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
|
||||
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
|
||||
if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) {
|
||||
if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
|
||||
REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
|
||||
REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
|
||||
REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
|
||||
}
|
||||
|
||||
ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pause btcoex timer and bt duty cycle timer
|
||||
*/
|
||||
void ath_btcoex_timer_pause(struct ath_softc *sc,
|
||||
struct ath_btcoex_info *btinfo)
|
||||
{
|
||||
|
||||
del_timer_sync(&btinfo->period_timer);
|
||||
|
||||
if (btinfo->hw_timer_enabled)
|
||||
ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
|
||||
|
||||
btinfo->hw_timer_enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (Re)start btcoex timers
|
||||
*/
|
||||
void ath_btcoex_timer_resume(struct ath_softc *sc,
|
||||
struct ath_btcoex_info *btinfo)
|
||||
{
|
||||
|
||||
DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers");
|
||||
|
||||
/* make sure duty cycle timer is also stopped when resuming */
|
||||
if (btinfo->hw_timer_enabled)
|
||||
ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
|
||||
|
||||
btinfo->bt_priority_cnt = 0;
|
||||
btinfo->bt_priority_time = jiffies;
|
||||
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
|
||||
|
||||
mod_timer(&btinfo->period_timer, jiffies);
|
||||
ah->btcoex_hw.enabled = false;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_btcoex_disable);
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef BTCOEX_H
|
||||
#define BTCOEX_H
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
#define ATH_WLANACTIVE_GPIO 5
|
||||
#define ATH_BTACTIVE_GPIO 6
|
||||
#define ATH_BTPRIORITY_GPIO 7
|
||||
@ -34,67 +36,25 @@ enum ath_btcoex_scheme {
|
||||
ATH_BTCOEX_CFG_3WIRE,
|
||||
};
|
||||
|
||||
enum ath_stomp_type {
|
||||
ATH_BTCOEX_NO_STOMP,
|
||||
ATH_BTCOEX_STOMP_ALL,
|
||||
ATH_BTCOEX_STOMP_LOW,
|
||||
ATH_BTCOEX_STOMP_NONE
|
||||
};
|
||||
|
||||
enum ath_bt_mode {
|
||||
ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */
|
||||
ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */
|
||||
ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */
|
||||
ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */
|
||||
};
|
||||
|
||||
struct ath_btcoex_config {
|
||||
u8 bt_time_extend;
|
||||
bool bt_txstate_extend;
|
||||
bool bt_txframe_extend;
|
||||
enum ath_bt_mode bt_mode; /* coexistence mode */
|
||||
bool bt_quiet_collision;
|
||||
bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/
|
||||
u8 bt_priority_time;
|
||||
u8 bt_first_slot_time;
|
||||
bool bt_hold_rx_clear;
|
||||
};
|
||||
|
||||
struct ath_btcoex_info {
|
||||
enum ath_btcoex_scheme btcoex_scheme;
|
||||
struct ath_btcoex_hw {
|
||||
enum ath_btcoex_scheme scheme;
|
||||
bool enabled;
|
||||
u8 wlanactive_gpio;
|
||||
u8 btactive_gpio;
|
||||
u8 btpriority_gpio;
|
||||
u8 bt_duty_cycle; /* BT duty cycle in percentage */
|
||||
int bt_stomp_type; /* Types of BT stomping */
|
||||
u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */
|
||||
u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */
|
||||
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
|
||||
u32 btcoex_no_stomp; /* in usec */
|
||||
u32 btcoex_period; /* in usec */
|
||||
u32 bt_priority_cnt;
|
||||
unsigned long bt_priority_time;
|
||||
bool hw_timer_enabled;
|
||||
spinlock_t btcoex_lock;
|
||||
struct timer_list period_timer; /* Timer for BT period */
|
||||
struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/
|
||||
};
|
||||
|
||||
bool ath_btcoex_supported(u16 subsysid);
|
||||
int ath9k_hw_btcoex_init(struct ath_hw *ah);
|
||||
bool ath9k_hw_btcoex_supported(struct ath_hw *ah);
|
||||
void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
|
||||
void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
|
||||
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum);
|
||||
void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
|
||||
u32 bt_weight,
|
||||
u32 wlan_weight);
|
||||
void ath9k_hw_btcoex_enable(struct ath_hw *ah);
|
||||
void ath9k_hw_btcoex_disable(struct ath_hw *ah);
|
||||
void ath_btcoex_timer_resume(struct ath_softc *sc,
|
||||
struct ath_btcoex_info *btinfo);
|
||||
void ath_btcoex_timer_pause(struct ath_softc *sc,
|
||||
struct ath_btcoex_info *btinfo);
|
||||
|
||||
static inline void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info,
|
||||
u32 bt_weight,
|
||||
u32 wlan_weight)
|
||||
{
|
||||
btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
|
||||
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
/* We can tune this as we go by monitoring really low values */
|
||||
#define ATH9K_NF_TOO_LOW -60
|
||||
@ -26,11 +26,11 @@
|
||||
static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
|
||||
{
|
||||
if (nf > ATH9K_NF_TOO_LOW) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"noise floor value detected (%d) is "
|
||||
"lower than what we think is a "
|
||||
"reasonable value (%d)\n",
|
||||
nf, ATH9K_NF_TOO_LOW);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
|
||||
"noise floor value detected (%d) is "
|
||||
"lower than what we think is a "
|
||||
"reasonable value (%d)\n",
|
||||
nf, ATH9K_NF_TOO_LOW);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -89,6 +89,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
|
||||
static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
int16_t nfarray[NUM_NF_READINGS])
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int16_t nf;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
@ -98,8 +99,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 0] is %d\n", nf);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 0] is %d\n", nf);
|
||||
nfarray[0] = nf;
|
||||
|
||||
if (!AR_SREV_9285(ah)) {
|
||||
@ -112,8 +113,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 1] is %d\n", nf);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 1] is %d\n", nf);
|
||||
nfarray[1] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
|
||||
@ -121,8 +122,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
AR_PHY_CH2_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 2] is %d\n", nf);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 2] is %d\n", nf);
|
||||
nfarray[2] = nf;
|
||||
}
|
||||
}
|
||||
@ -136,8 +137,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 0] is %d\n", nf);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 0] is %d\n", nf);
|
||||
nfarray[3] = nf;
|
||||
|
||||
if (!AR_SREV_9285(ah)) {
|
||||
@ -150,8 +151,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 1] is %d\n", nf);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 1] is %d\n", nf);
|
||||
nfarray[4] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
|
||||
@ -159,8 +160,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
|
||||
AR_PHY_CH2_EXT_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 2] is %d\n", nf);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 2] is %d\n", nf);
|
||||
nfarray[5] = nf;
|
||||
}
|
||||
}
|
||||
@ -188,6 +189,8 @@ static bool getNoiseFloorThresh(struct ath_hw *ah,
|
||||
static void ath9k_hw_setup_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
|
||||
currCal->calData->calCountMax);
|
||||
@ -195,23 +198,23 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah,
|
||||
switch (currCal->calData->calType) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"starting IQ Mismatch Calibration\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"starting IQ Mismatch Calibration\n");
|
||||
break;
|
||||
case ADC_GAIN_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"starting ADC Gain Calibration\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"starting ADC Gain Calibration\n");
|
||||
break;
|
||||
case ADC_DC_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"starting ADC DC Calibration\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"starting ADC DC Calibration\n");
|
||||
break;
|
||||
case ADC_DC_INIT_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"starting Init ADC DC Calibration\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"starting Init ADC DC Calibration\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -278,7 +281,7 @@ static bool ath9k_hw_per_calibration(struct ath_hw *ah,
|
||||
static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
|
||||
enum ath9k_cal_types calType)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
|
||||
switch (calType & ah->supp_cals) {
|
||||
case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
|
||||
@ -304,11 +307,11 @@ static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ah->totalIqCorrMeas[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
|
||||
ah->cal_samples, i, ah->totalPowerMeasI[i],
|
||||
ah->totalPowerMeasQ[i],
|
||||
ah->totalIqCorrMeas[i]);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
|
||||
ah->cal_samples, i, ah->totalPowerMeasI[i],
|
||||
ah->totalPowerMeasQ[i],
|
||||
ah->totalIqCorrMeas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,14 +329,14 @@ static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
|
||||
ah->totalAdcQEvenPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
|
||||
"oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ah->cal_samples, i,
|
||||
ah->totalAdcIOddPhase[i],
|
||||
ah->totalAdcIEvenPhase[i],
|
||||
ah->totalAdcQOddPhase[i],
|
||||
ah->totalAdcQEvenPhase[i]);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
|
||||
"oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ah->cal_samples, i,
|
||||
ah->totalAdcIOddPhase[i],
|
||||
ah->totalAdcIEvenPhase[i],
|
||||
ah->totalAdcQOddPhase[i],
|
||||
ah->totalAdcQEvenPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,19 +354,20 @@ static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
|
||||
ah->totalAdcDcOffsetQEvenPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
|
||||
"oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ah->cal_samples, i,
|
||||
ah->totalAdcDcOffsetIOddPhase[i],
|
||||
ah->totalAdcDcOffsetIEvenPhase[i],
|
||||
ah->totalAdcDcOffsetQOddPhase[i],
|
||||
ah->totalAdcDcOffsetQEvenPhase[i]);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
|
||||
"oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ah->cal_samples, i,
|
||||
ah->totalAdcDcOffsetIOddPhase[i],
|
||||
ah->totalAdcDcOffsetIEvenPhase[i],
|
||||
ah->totalAdcDcOffsetQOddPhase[i],
|
||||
ah->totalAdcDcOffsetQEvenPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 powerMeasQ, powerMeasI, iqCorrMeas;
|
||||
u32 qCoffDenom, iCoffDenom;
|
||||
int32_t qCoff, iCoff;
|
||||
@ -374,13 +378,13 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
powerMeasQ = ah->totalPowerMeasQ[i];
|
||||
iqCorrMeas = ah->totalIqCorrMeas[i];
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Starting IQ Cal and Correction for Chain %d\n",
|
||||
i);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Starting IQ Cal and Correction for Chain %d\n",
|
||||
i);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Orignal: Chn %diq_corr_meas = 0x%08x\n",
|
||||
i, ah->totalIqCorrMeas[i]);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Orignal: Chn %diq_corr_meas = 0x%08x\n",
|
||||
i, ah->totalIqCorrMeas[i]);
|
||||
|
||||
iqCorrNeg = 0;
|
||||
|
||||
@ -389,27 +393,28 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
iqCorrNeg = 1;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
|
||||
iqCorrNeg);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
|
||||
ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
|
||||
iqCorrNeg);
|
||||
|
||||
iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
|
||||
qCoffDenom = powerMeasQ / 64;
|
||||
|
||||
if (powerMeasQ != 0) {
|
||||
if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
|
||||
(qCoffDenom != 0)) {
|
||||
iCoff = iqCorrMeas / iCoffDenom;
|
||||
qCoff = powerMeasI / qCoffDenom - 64;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d qCoff = 0x%08x\n", i, qCoff);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d qCoff = 0x%08x\n", i, qCoff);
|
||||
|
||||
iCoff = iCoff & 0x3f;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
if (iqCorrNeg == 0x0)
|
||||
iCoff = 0x40 - iCoff;
|
||||
|
||||
@ -418,9 +423,9 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
else if (qCoff <= -16)
|
||||
qCoff = 16;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
|
||||
i, iCoff, qCoff);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
|
||||
i, iCoff, qCoff);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
|
||||
@ -428,9 +433,9 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
|
||||
qCoff);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"IQ Cal and Correction done for Chain %d\n",
|
||||
i);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"IQ Cal and Correction done for Chain %d\n",
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,6 +445,7 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||
|
||||
static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
|
||||
u32 qGainMismatch, iGainMismatch, val, i;
|
||||
|
||||
@ -449,21 +455,21 @@ static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
qOddMeasOffset = ah->totalAdcQOddPhase[i];
|
||||
qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Starting ADC Gain Cal for Chain %d\n", i);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Starting ADC Gain Cal for Chain %d\n", i);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
|
||||
iOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_i = 0x%08x\n", i,
|
||||
iEvenMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
|
||||
qOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_q = 0x%08x\n", i,
|
||||
qEvenMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
|
||||
iOddMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_i = 0x%08x\n", i,
|
||||
iEvenMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
|
||||
qOddMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_q = 0x%08x\n", i,
|
||||
qEvenMeasOffset);
|
||||
|
||||
if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
|
||||
iGainMismatch =
|
||||
@ -473,20 +479,20 @@ static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
((qOddMeasOffset * 32) /
|
||||
qEvenMeasOffset) & 0x3f;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d gain_mismatch_i = 0x%08x\n", i,
|
||||
iGainMismatch);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d gain_mismatch_q = 0x%08x\n", i,
|
||||
qGainMismatch);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d gain_mismatch_i = 0x%08x\n", i,
|
||||
iGainMismatch);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d gain_mismatch_q = 0x%08x\n", i,
|
||||
qGainMismatch);
|
||||
|
||||
val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
|
||||
val &= 0xfffff000;
|
||||
val |= (qGainMismatch) | (iGainMismatch << 6);
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"ADC Gain Cal done for Chain %d\n", i);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"ADC Gain Cal done for Chain %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,6 +503,7 @@ static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
|
||||
static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 iOddMeasOffset, iEvenMeasOffset, val, i;
|
||||
int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
|
||||
const struct ath9k_percal_data *calData =
|
||||
@ -510,41 +517,41 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
|
||||
qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Starting ADC DC Offset Cal for Chain %d\n", i);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Starting ADC DC Offset Cal for Chain %d\n", i);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_i = %d\n", i,
|
||||
iOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_i = %d\n", i,
|
||||
iEvenMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_q = %d\n", i,
|
||||
qOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_q = %d\n", i,
|
||||
qEvenMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_i = %d\n", i,
|
||||
iOddMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_i = %d\n", i,
|
||||
iEvenMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_q = %d\n", i,
|
||||
qOddMeasOffset);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_q = %d\n", i,
|
||||
qEvenMeasOffset);
|
||||
|
||||
iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
|
||||
numSamples) & 0x1ff;
|
||||
qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
|
||||
numSamples) & 0x1ff;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
|
||||
iDcMismatch);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
|
||||
qDcMismatch);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
|
||||
iDcMismatch);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
|
||||
qDcMismatch);
|
||||
|
||||
val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
|
||||
val &= 0xc0000fff;
|
||||
val |= (qDcMismatch << 12) | (iDcMismatch << 21);
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"ADC DC Offset Cal done for Chain %d\n", i);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"ADC DC Offset Cal done for Chain %d\n", i);
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
|
||||
@ -555,7 +562,8 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
|
||||
/* This is done for the currently configured channel */
|
||||
bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_conf *conf = &common->hw->conf;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
|
||||
if (!ah->curchan)
|
||||
@ -568,24 +576,25 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
|
||||
return true;
|
||||
|
||||
if (currCal->calState != CAL_DONE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Calibration state incorrect, %d\n",
|
||||
currCal->calState);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Calibration state incorrect, %d\n",
|
||||
currCal->calState);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
|
||||
return true;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Resetting Cal %d state for channel %u\n",
|
||||
currCal->calData->calType, conf->channel->center_freq);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"Resetting Cal %d state for channel %u\n",
|
||||
currCal->calData->calType, conf->channel->center_freq);
|
||||
|
||||
ah->curchan->CalValid &= ~currCal->calData->calType;
|
||||
currCal->calState = CAL_WAITING;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
|
||||
|
||||
void ath9k_hw_start_nfcal(struct ath_hw *ah)
|
||||
{
|
||||
@ -645,11 +654,11 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
|
||||
for (j = 0; j < 1000; j++) {
|
||||
for (j = 0; j < 5; j++) {
|
||||
if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_NF) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
@ -665,6 +674,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
int16_t ath9k_hw_getnf(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int16_t nf, nfThresh;
|
||||
int16_t nfarray[NUM_NF_READINGS] = { 0 };
|
||||
struct ath9k_nfcal_hist *h;
|
||||
@ -672,8 +682,8 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
|
||||
|
||||
chan->channelFlags &= (~CHANNEL_CW_INT);
|
||||
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF did not complete in calibration window\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"NF did not complete in calibration window\n");
|
||||
nf = 0;
|
||||
chan->rawNoiseFloor = nf;
|
||||
return chan->rawNoiseFloor;
|
||||
@ -682,10 +692,10 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
|
||||
nf = nfarray[0];
|
||||
if (getNoiseFloorThresh(ah, c->band, &nfThresh)
|
||||
&& nf > nfThresh) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"noise floor failed detected; "
|
||||
"detected %d, threshold %d\n",
|
||||
nf, nfThresh);
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"noise floor failed detected; "
|
||||
"detected %d, threshold %d\n",
|
||||
nf, nfThresh);
|
||||
chan->channelFlags |= CHANNEL_CW_INT;
|
||||
}
|
||||
}
|
||||
@ -737,45 +747,67 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
|
||||
return nf;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_getchan_noise);
|
||||
|
||||
static void ath9k_olc_temp_compensation(struct ath_hw *ah)
|
||||
static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah)
|
||||
{
|
||||
u32 rddata, i;
|
||||
int delta, currPDADC, regval, slope;
|
||||
u32 rddata;
|
||||
int32_t delta, currPDADC, slope;
|
||||
|
||||
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
|
||||
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
|
||||
if (ah->initPDADC == 0 || currPDADC == 0) {
|
||||
/*
|
||||
* Zero value indicates that no frames have been transmitted yet,
|
||||
* can't do temperature compensation until frames are transmitted.
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
|
||||
|
||||
if (slope == 0) { /* to avoid divide by zero case */
|
||||
delta = 0;
|
||||
} else {
|
||||
delta = ((currPDADC - ah->initPDADC)*4) / slope;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_olc_temp_compensation(struct ath_hw *ah)
|
||||
{
|
||||
u32 rddata, i;
|
||||
int delta, currPDADC, regval;
|
||||
|
||||
if (OLC_FOR_AR9287_10_LATER) {
|
||||
ath9k_olc_temp_compensation_9287(ah);
|
||||
} else {
|
||||
rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
|
||||
currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
|
||||
|
||||
if (ah->initPDADC == 0 || currPDADC == 0) {
|
||||
return;
|
||||
} else {
|
||||
slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
|
||||
if (slope == 0)
|
||||
delta = 0;
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
|
||||
delta = (currPDADC - ah->initPDADC + 4) / 8;
|
||||
else
|
||||
delta = ((currPDADC - ah->initPDADC)*4) / slope;
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
|
||||
AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
|
||||
}
|
||||
} else {
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
|
||||
delta = (currPDADC - ah->initPDADC + 4) / 8;
|
||||
else
|
||||
delta = (currPDADC - ah->initPDADC + 5) / 10;
|
||||
delta = (currPDADC - ah->initPDADC + 5) / 10;
|
||||
|
||||
if (delta != ah->PDADCdelta) {
|
||||
ah->PDADCdelta = delta;
|
||||
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
regval = ah->originalGain[i] - delta;
|
||||
if (regval < 0)
|
||||
regval = 0;
|
||||
if (delta != ah->PDADCdelta) {
|
||||
ah->PDADCdelta = delta;
|
||||
for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
|
||||
regval = ah->originalGain[i] - delta;
|
||||
if (regval < 0)
|
||||
regval = 0;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
|
||||
AR_PHY_TX_GAIN, regval);
|
||||
REG_RMW_FIELD(ah,
|
||||
AR_PHY_TX_GAIN_TBL1 + i * 4,
|
||||
AR_PHY_TX_GAIN, regval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -875,7 +907,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
|
||||
|
||||
static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
|
||||
{
|
||||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 regVal;
|
||||
int i, offset, offs_6_1, offs_0;
|
||||
u32 ccomp_org, reg_field;
|
||||
@ -889,7 +921,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
|
||||
{ 0x7838, 0 },
|
||||
};
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
|
||||
|
||||
/* PA CAL is not needed for high power solution */
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
|
||||
@ -1036,9 +1068,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
|
||||
return iscaldone;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_calibrate);
|
||||
|
||||
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
|
||||
if (IS_CHAN_HT20(chan)) {
|
||||
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
|
||||
@ -1049,9 +1084,9 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset "
|
||||
"calibration failed to complete in "
|
||||
"1ms; noisy ??\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE, "offset "
|
||||
"calibration failed to complete in "
|
||||
"1ms; noisy ??\n");
|
||||
return false;
|
||||
}
|
||||
REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
|
||||
@ -1064,8 +1099,8 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration "
|
||||
"failed to complete in 1ms; noisy ??\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
|
||||
"failed to complete in 1ms; noisy ??\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1078,6 +1113,8 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
|
||||
bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
if (!ar9285_clc(ah, chan))
|
||||
return false;
|
||||
@ -1098,9 +1135,9 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
/* Poll for offset calibration complete */
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"offset calibration failed to complete in 1ms; "
|
||||
"noisy environment?\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"offset calibration failed to "
|
||||
"complete in 1ms; noisy environment?\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1128,20 +1165,20 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
|
||||
INIT_CAL(&ah->adcgain_caldata);
|
||||
INSERT_CAL(ah, &ah->adcgain_caldata);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"enabling ADC Gain Calibration.\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"enabling ADC Gain Calibration.\n");
|
||||
}
|
||||
if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
|
||||
INIT_CAL(&ah->adcdc_caldata);
|
||||
INSERT_CAL(ah, &ah->adcdc_caldata);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"enabling ADC DC Calibration.\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"enabling ADC DC Calibration.\n");
|
||||
}
|
||||
if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"enabling IQ Calibration.\n");
|
||||
ath_print(common, ATH_DBG_CALIBRATE,
|
||||
"enabling IQ Calibration.\n");
|
||||
}
|
||||
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef CALIB_H
|
||||
#define CALIB_H
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
extern const struct ath9k_percal_data iq_cal_multi_sample;
|
||||
extern const struct ath9k_percal_data iq_cal_single_sample;
|
||||
extern const struct ath9k_percal_data adc_gain_cal_multi_sample;
|
||||
|
@ -18,26 +18,13 @@
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
static unsigned int ath9k_debug = DBG_DEFAULT;
|
||||
module_param_named(debug, ath9k_debug, uint, 0);
|
||||
#define REG_WRITE_D(_ah, _reg, _val) \
|
||||
ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
|
||||
#define REG_READ_D(_ah, _reg) \
|
||||
ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
|
||||
|
||||
static struct dentry *ath9k_debugfs_root;
|
||||
|
||||
void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
|
||||
{
|
||||
if (!sc)
|
||||
return;
|
||||
|
||||
if (sc->debug.debug_mask & dbg_mask) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
printk(KERN_DEBUG "ath9k: ");
|
||||
vprintk(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath9k_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
@ -48,10 +35,11 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask);
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
@ -59,6 +47,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
unsigned long mask;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
@ -71,7 +60,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
|
||||
if (strict_strtoul(buf, 0, &mask))
|
||||
return -EINVAL;
|
||||
|
||||
sc->debug.debug_mask = mask;
|
||||
common->debug_mask = mask;
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -95,7 +84,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
REG_WRITE(ah, AR_MACMISC,
|
||||
REG_WRITE_D(ah, AR_MACMISC,
|
||||
((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
|
||||
(AR_MACMISC_MISC_OBS_BUS_1 <<
|
||||
AR_MACMISC_MISC_OBS_BUS_MSB_S)));
|
||||
@ -107,7 +96,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
||||
if (i % 4 == 0)
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "\n");
|
||||
|
||||
val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
|
||||
val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
|
||||
i, val[i]);
|
||||
}
|
||||
@ -157,9 +146,9 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
||||
(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
|
||||
|
||||
len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
|
||||
REG_READ(ah, AR_OBS_BUS_1));
|
||||
REG_READ_D(ah, AR_OBS_BUS_1));
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
|
||||
"AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR));
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
@ -376,12 +365,12 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
|
||||
aphy->chan_idx, aphy->chan_is_ht);
|
||||
}
|
||||
|
||||
put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr);
|
||||
put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
|
||||
put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
|
||||
put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"addr: %pM\n", addr);
|
||||
put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr);
|
||||
put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
|
||||
put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr);
|
||||
put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"addrmask: %pM\n", addr);
|
||||
|
||||
@ -568,9 +557,10 @@ static const struct file_operations fops_xmit = {
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
int ath9k_init_debug(struct ath_softc *sc)
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
sc->debug.debug_mask = ath9k_debug;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
|
||||
if (!ath9k_debugfs_root)
|
||||
return -ENOENT;
|
||||
@ -619,12 +609,15 @@ int ath9k_init_debug(struct ath_softc *sc)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
ath9k_exit_debug(sc);
|
||||
ath9k_exit_debug(ah);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void ath9k_exit_debug(struct ath_softc *sc)
|
||||
void ath9k_exit_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
|
||||
debugfs_remove(sc->debug.debugfs_xmit);
|
||||
debugfs_remove(sc->debug.debugfs_wiphy);
|
||||
debugfs_remove(sc->debug.debugfs_rcstat);
|
||||
|
@ -17,25 +17,7 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
enum ATH_DEBUG {
|
||||
ATH_DBG_RESET = 0x00000001,
|
||||
ATH_DBG_QUEUE = 0x00000002,
|
||||
ATH_DBG_EEPROM = 0x00000004,
|
||||
ATH_DBG_CALIBRATE = 0x00000008,
|
||||
ATH_DBG_INTERRUPT = 0x00000010,
|
||||
ATH_DBG_REGULATORY = 0x00000020,
|
||||
ATH_DBG_ANI = 0x00000040,
|
||||
ATH_DBG_XMIT = 0x00000080,
|
||||
ATH_DBG_BEACON = 0x00000100,
|
||||
ATH_DBG_CONFIG = 0x00000200,
|
||||
ATH_DBG_FATAL = 0x00000400,
|
||||
ATH_DBG_PS = 0x00000800,
|
||||
ATH_DBG_HWTIMER = 0x00001000,
|
||||
ATH_DBG_BTCOEX = 0x00002000,
|
||||
ATH_DBG_ANY = 0xffffffff
|
||||
};
|
||||
|
||||
#define DBG_DEFAULT (ATH_DBG_FATAL)
|
||||
#include "hw.h"
|
||||
|
||||
struct ath_txq;
|
||||
struct ath_buf;
|
||||
@ -140,7 +122,6 @@ struct ath_stats {
|
||||
};
|
||||
|
||||
struct ath9k_debug {
|
||||
int debug_mask;
|
||||
struct dentry *debugfs_phy;
|
||||
struct dentry *debugfs_debug;
|
||||
struct dentry *debugfs_dma;
|
||||
@ -151,9 +132,9 @@ struct ath9k_debug {
|
||||
struct ath_stats stats;
|
||||
};
|
||||
|
||||
void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
|
||||
int ath9k_init_debug(struct ath_softc *sc);
|
||||
void ath9k_exit_debug(struct ath_softc *sc);
|
||||
int ath9k_init_debug(struct ath_hw *ah);
|
||||
void ath9k_exit_debug(struct ath_hw *ah);
|
||||
|
||||
int ath9k_debug_create_root(void);
|
||||
void ath9k_debug_remove_root(void);
|
||||
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
|
||||
@ -165,17 +146,12 @@ void ath_debug_stat_retries(struct ath_softc *sc, int rix,
|
||||
|
||||
#else
|
||||
|
||||
static inline void DPRINTF(struct ath_softc *sc, int dbg_mask,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int ath9k_init_debug(struct ath_softc *sc)
|
||||
static inline int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath9k_exit_debug(struct ath_softc *sc)
|
||||
static inline void ath9k_exit_debug(struct ath_hw *ah)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
|
||||
{
|
||||
@ -83,11 +83,9 @@ bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||
bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_softc *sc = ah->ah_sc;
|
||||
|
||||
return sc->bus_ops->eeprom_read(ah, off, data);
|
||||
return common->bus_ops->eeprom_read(common, off, data);
|
||||
}
|
||||
|
||||
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#ifndef EEPROM_H
|
||||
#define EEPROM_H
|
||||
|
||||
#include "../ath.h"
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#define AH_USE_EEPROM 0x1
|
||||
@ -133,6 +134,7 @@
|
||||
#define AR5416_EEP_MINOR_VER_17 0x11
|
||||
#define AR5416_EEP_MINOR_VER_19 0x13
|
||||
#define AR5416_EEP_MINOR_VER_20 0x14
|
||||
#define AR5416_EEP_MINOR_VER_21 0x15
|
||||
#define AR5416_EEP_MINOR_VER_22 0x16
|
||||
|
||||
#define AR5416_NUM_5G_CAL_PIERS 8
|
||||
@ -153,7 +155,7 @@
|
||||
#define AR5416_BCHAN_UNUSED 0xFF
|
||||
#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
|
||||
#define AR5416_MAX_CHAINS 3
|
||||
#define AR5416_PWR_TABLE_OFFSET -5
|
||||
#define AR5416_PWR_TABLE_OFFSET_DB -5
|
||||
|
||||
/* Rx gain type values */
|
||||
#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
|
||||
@ -301,7 +303,7 @@ struct base_eep_header {
|
||||
u8 txGainType;
|
||||
u8 rcChainMask;
|
||||
u8 desiredScaleCCK;
|
||||
u8 power_table_offset;
|
||||
u8 pwr_table_offset;
|
||||
u8 frac_n_5g;
|
||||
u8 futureBase_3[21];
|
||||
} __packed;
|
||||
@ -638,6 +640,7 @@ struct ar9287_eeprom {
|
||||
} __packed;
|
||||
|
||||
enum reg_ext_bitmap {
|
||||
REG_EXT_FCC_MIDBAND = 0,
|
||||
REG_EXT_JAPAN_MIDBAND = 1,
|
||||
REG_EXT_FCC_DFS_HT40 = 2,
|
||||
REG_EXT_JAPAN_NONDFS_HT40 = 3,
|
||||
@ -684,7 +687,7 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
|
||||
int16_t targetRight);
|
||||
bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
|
||||
u16 *indexL, u16 *indexR);
|
||||
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
|
||||
bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
|
||||
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
|
||||
u8 *pVpdList, u16 numIntercepts,
|
||||
u8 *pRetVpdList);
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
|
||||
{
|
||||
@ -29,20 +29,21 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
|
||||
static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u16 *eep_data = (u16 *)&ah->eeprom.map4k;
|
||||
int addr, eep_start_loc = 0;
|
||||
|
||||
eep_start_loc = 64;
|
||||
|
||||
if (!ath9k_hw_use_flash(ah)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Reading from EEPROM, not flash\n");
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Reading from EEPROM, not flash\n");
|
||||
}
|
||||
|
||||
for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
|
||||
if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Unable to read eeprom region \n");
|
||||
if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Unable to read eeprom region \n");
|
||||
return false;
|
||||
}
|
||||
eep_data++;
|
||||
@ -55,6 +56,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
|
||||
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ar5416_eeprom_4k *eep =
|
||||
(struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
|
||||
u16 *eepdata, temp, magic, magic2;
|
||||
@ -64,15 +66,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||
|
||||
|
||||
if (!ath9k_hw_use_flash(ah)) {
|
||||
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
|
||||
if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
|
||||
&magic)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Reading Magic # failed\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Reading Magic # failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Read Magic = 0x%04X\n", magic);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Read Magic = 0x%04X\n", magic);
|
||||
|
||||
if (magic != AR5416_EEPROM_MAGIC) {
|
||||
magic2 = swab16(magic);
|
||||
@ -87,16 +89,16 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||
eepdata++;
|
||||
}
|
||||
} else {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Invalid EEPROM Magic. "
|
||||
"endianness mismatch.\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Invalid EEPROM Magic. "
|
||||
"endianness mismatch.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
|
||||
need_swap ? "True" : "False");
|
||||
ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
|
||||
need_swap ? "True" : "False");
|
||||
|
||||
if (need_swap)
|
||||
el = swab16(ah->eeprom.map4k.baseEepHeader.length);
|
||||
@ -117,8 +119,8 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||
u32 integer;
|
||||
u16 word;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"EEPROM Endianness is not native.. Changing\n");
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"EEPROM Endianness is not native.. Changing\n");
|
||||
|
||||
word = swab16(eep->baseEepHeader.length);
|
||||
eep->baseEepHeader.length = word;
|
||||
@ -160,9 +162,9 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
|
||||
|
||||
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
|
||||
ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -208,6 +210,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
|
||||
return pBase->rxMask;
|
||||
case EEP_FRAC_N_5G:
|
||||
return 0;
|
||||
case EEP_PWR_TABLE_OFFSET:
|
||||
return AR5416_PWR_TABLE_OFFSET_DB;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -385,6 +389,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
int16_t *pTxPowerIndexOffset)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
|
||||
struct cal_data_per_freq_4k *pRawDataset;
|
||||
u8 *pCalBChans = NULL;
|
||||
@ -470,21 +475,21 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
|
||||
((pdadcValues[4 * j + 3] & 0xFF) << 24);
|
||||
REG_WRITE(ah, regOffset, reg32);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"PDADC (%d,%4x): %4.4x %8.8x\n",
|
||||
i, regChainOffset, regOffset,
|
||||
reg32);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"PDADC: Chain %d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d |\n",
|
||||
i, 4 * j, pdadcValues[4 * j],
|
||||
4 * j + 1, pdadcValues[4 * j + 1],
|
||||
4 * j + 2, pdadcValues[4 * j + 2],
|
||||
4 * j + 3,
|
||||
pdadcValues[4 * j + 3]);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"PDADC (%d,%4x): %4.4x %8.8x\n",
|
||||
i, regChainOffset, regOffset,
|
||||
reg32);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"PDADC: Chain %d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d |\n",
|
||||
i, 4 * j, pdadcValues[4 * j],
|
||||
4 * j + 1, pdadcValues[4 * j + 1],
|
||||
4 * j + 2, pdadcValues[4 * j + 2],
|
||||
4 * j + 3,
|
||||
pdadcValues[4 * j + 3]);
|
||||
|
||||
regOffset += 4;
|
||||
}
|
||||
@ -750,7 +755,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
|
||||
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
}
|
||||
|
||||
/* OFDM power per rate */
|
||||
@ -1148,20 +1153,21 @@ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
|
||||
{
|
||||
#define EEP_MAP4K_SPURCHAN \
|
||||
(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
u16 spur_val = AR_NO_SPUR;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Getting spur idx %d is2Ghz. %d val %x\n",
|
||||
i, is2GHz, ah->config.spurchans[i][is2GHz]);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Getting spur idx %d is2Ghz. %d val %x\n",
|
||||
i, is2GHz, ah->config.spurchans[i][is2GHz]);
|
||||
|
||||
switch (ah->config.spurmode) {
|
||||
case SPUR_DISABLE:
|
||||
break;
|
||||
case SPUR_ENABLE_IOCTL:
|
||||
spur_val = ah->config.spurchans[i][is2GHz];
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Getting spur val from new loc. %d\n", spur_val);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Getting spur val from new loc. %d\n", spur_val);
|
||||
break;
|
||||
case SPUR_ENABLE_EEPROM:
|
||||
spur_val = EEP_MAP4K_SPURCHAN;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)
|
||||
{
|
||||
@ -29,20 +29,22 @@ static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah)
|
||||
static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u16 *eep_data;
|
||||
int addr, eep_start_loc = AR9287_EEP_START_LOC;
|
||||
eep_data = (u16 *)eep;
|
||||
|
||||
if (!ath9k_hw_use_flash(ah)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Reading from EEPROM, not flash\n");
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Reading from EEPROM, not flash\n");
|
||||
}
|
||||
|
||||
for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
|
||||
addr++) {
|
||||
if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Unable to read eeprom region \n");
|
||||
if (!ath9k_hw_nvram_read(common,
|
||||
addr + eep_start_loc, eep_data)) {
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Unable to read eeprom region \n");
|
||||
return false;
|
||||
}
|
||||
eep_data++;
|
||||
@ -57,17 +59,18 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
int i, addr;
|
||||
bool need_swap = false;
|
||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!ath9k_hw_use_flash(ah)) {
|
||||
if (!ath9k_hw_nvram_read
|
||||
(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Reading Magic # failed\n");
|
||||
if (!ath9k_hw_nvram_read(common,
|
||||
AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Reading Magic # failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Read Magic = 0x%04X\n", magic);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Read Magic = 0x%04X\n", magic);
|
||||
if (magic != AR5416_EEPROM_MAGIC) {
|
||||
magic2 = swab16(magic);
|
||||
|
||||
@ -83,15 +86,15 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
eepdata++;
|
||||
}
|
||||
} else {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Invalid EEPROM Magic. "
|
||||
"endianness mismatch.\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Invalid EEPROM Magic. "
|
||||
"endianness mismatch.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ?
|
||||
"True" : "False");
|
||||
ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ?
|
||||
"True" : "False");
|
||||
|
||||
if (need_swap)
|
||||
el = swab16(ah->eeprom.map9287.baseEepHeader.length);
|
||||
@ -148,9 +151,9 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
|
||||
|
||||
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
|
||||
|| ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -436,6 +439,7 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
int16_t *pTxPowerIndexOffset)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct cal_data_per_freq_ar9287 *pRawDataset;
|
||||
struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
|
||||
u8 *pCalBChans = NULL;
|
||||
@ -564,24 +568,25 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
|
||||
& 0xFF) << 24) ;
|
||||
REG_WRITE(ah, regOffset, reg32);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"PDADC (%d,%4x): %4.4x %8.8x\n",
|
||||
i, regChainOffset, regOffset,
|
||||
reg32);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"PDADC (%d,%4x): %4.4x "
|
||||
"%8.8x\n",
|
||||
i, regChainOffset, regOffset,
|
||||
reg32);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"PDADC: Chain %d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d |\n",
|
||||
i, 4 * j, pdadcValues[4 * j],
|
||||
4 * j + 1,
|
||||
pdadcValues[4 * j + 1],
|
||||
4 * j + 2,
|
||||
pdadcValues[4 * j + 2],
|
||||
4 * j + 3,
|
||||
pdadcValues[4 * j + 3]);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"PDADC: Chain %d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d |\n",
|
||||
i, 4 * j, pdadcValues[4 * j],
|
||||
4 * j + 1,
|
||||
pdadcValues[4 * j + 1],
|
||||
4 * j + 2,
|
||||
pdadcValues[4 * j + 2],
|
||||
4 * j + 3,
|
||||
pdadcValues[4 * j + 3]);
|
||||
|
||||
regOffset += 4;
|
||||
}
|
||||
@ -831,6 +836,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
|
||||
{
|
||||
#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
|
||||
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
|
||||
struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
|
||||
@ -966,8 +972,8 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
|
||||
INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1138,19 +1144,20 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
|
||||
{
|
||||
#define EEP_MAP9287_SPURCHAN \
|
||||
(ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u16 spur_val = AR_NO_SPUR;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Getting spur idx %d is2Ghz. %d val %x\n",
|
||||
i, is2GHz, ah->config.spurchans[i][is2GHz]);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Getting spur idx %d is2Ghz. %d val %x\n",
|
||||
i, is2GHz, ah->config.spurchans[i][is2GHz]);
|
||||
|
||||
switch (ah->config.spurmode) {
|
||||
case SPUR_DISABLE:
|
||||
break;
|
||||
case SPUR_ENABLE_IOCTL:
|
||||
spur_val = ah->config.spurchans[i][is2GHz];
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Getting spur val from new loc. %d\n", spur_val);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Getting spur val from new loc. %d\n", spur_val);
|
||||
break;
|
||||
case SPUR_ENABLE_EEPROM:
|
||||
spur_val = EEP_MAP9287_SPURCHAN;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static void ath9k_get_txgain_index(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
@ -89,14 +89,15 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
|
||||
static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u16 *eep_data = (u16 *)&ah->eeprom.def;
|
||||
int addr, ar5416_eep_start_loc = 0x100;
|
||||
|
||||
for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
|
||||
if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
|
||||
if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
|
||||
eep_data)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Unable to read eeprom region\n");
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
|
||||
"Unable to read eeprom region\n");
|
||||
return false;
|
||||
}
|
||||
eep_data++;
|
||||
@ -109,19 +110,20 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416_eeprom_def *eep =
|
||||
(struct ar5416_eeprom_def *) &ah->eeprom.def;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u16 *eepdata, temp, magic, magic2;
|
||||
u32 sum = 0, el;
|
||||
bool need_swap = false;
|
||||
int i, addr, size;
|
||||
|
||||
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
|
||||
if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
|
||||
ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_use_flash(ah)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Read Magic = 0x%04X\n", magic);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Read Magic = 0x%04X\n", magic);
|
||||
|
||||
if (magic != AR5416_EEPROM_MAGIC) {
|
||||
magic2 = swab16(magic);
|
||||
@ -137,16 +139,16 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||
eepdata++;
|
||||
}
|
||||
} else {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Invalid EEPROM Magic. "
|
||||
"Endianness mismatch.\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Invalid EEPROM Magic. "
|
||||
"Endianness mismatch.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
|
||||
need_swap ? "True" : "False");
|
||||
ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
|
||||
need_swap ? "True" : "False");
|
||||
|
||||
if (need_swap)
|
||||
el = swab16(ah->eeprom.def.baseEepHeader.length);
|
||||
@ -167,8 +169,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||
u32 integer, j;
|
||||
u16 word;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"EEPROM Endianness is not native.. Changing.\n");
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"EEPROM Endianness is not native.. Changing.\n");
|
||||
|
||||
word = swab16(eep->baseEepHeader.length);
|
||||
eep->baseEepHeader.length = word;
|
||||
@ -214,8 +216,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
|
||||
|
||||
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
|
||||
ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
|
||||
sum, ah->eep_ops->get_eeprom_ver(ah));
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -289,6 +291,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
|
||||
return pBase->frac_n_5g;
|
||||
else
|
||||
return 0;
|
||||
case EEP_PWR_TABLE_OFFSET:
|
||||
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21)
|
||||
return pBase->pwr_table_offset;
|
||||
else
|
||||
return AR5416_PWR_TABLE_OFFSET_DB;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -739,6 +746,76 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
return;
|
||||
}
|
||||
|
||||
static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
|
||||
u16 *gb,
|
||||
u16 numXpdGain,
|
||||
u16 pdGainOverlap_t2,
|
||||
int8_t pwr_table_offset,
|
||||
int16_t *diff)
|
||||
|
||||
{
|
||||
u16 k;
|
||||
|
||||
/* Prior to writing the boundaries or the pdadc vs. power table
|
||||
* into the chip registers the default starting point on the pdadc
|
||||
* vs. power table needs to be checked and the curve boundaries
|
||||
* adjusted accordingly
|
||||
*/
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
u16 gb_limit;
|
||||
|
||||
if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
|
||||
/* get the difference in dB */
|
||||
*diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB);
|
||||
/* get the number of half dB steps */
|
||||
*diff *= 2;
|
||||
/* change the original gain boundary settings
|
||||
* by the number of half dB steps
|
||||
*/
|
||||
for (k = 0; k < numXpdGain; k++)
|
||||
gb[k] = (u16)(gb[k] - *diff);
|
||||
}
|
||||
/* Because of a hardware limitation, ensure the gain boundary
|
||||
* is not larger than (63 - overlap)
|
||||
*/
|
||||
gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2);
|
||||
|
||||
for (k = 0; k < numXpdGain; k++)
|
||||
gb[k] = (u16)min(gb_limit, gb[k]);
|
||||
}
|
||||
|
||||
return *diff;
|
||||
}
|
||||
|
||||
static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
|
||||
int8_t pwr_table_offset,
|
||||
int16_t diff,
|
||||
u8 *pdadcValues)
|
||||
{
|
||||
#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff)
|
||||
u16 k;
|
||||
|
||||
/* If this is a board that has a pwrTableOffset that differs from
|
||||
* the default AR5416_PWR_TABLE_OFFSET_DB then the start of the
|
||||
* pdadc vs pwr table needs to be adjusted prior to writing to the
|
||||
* chip.
|
||||
*/
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
|
||||
/* shift the table to start at the new offset */
|
||||
for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) {
|
||||
pdadcValues[k] = pdadcValues[k + diff];
|
||||
}
|
||||
|
||||
/* fill the back of the table */
|
||||
for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) {
|
||||
pdadcValues[k] = pdadcValues[NUM_PDADC(diff)];
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef NUM_PDADC
|
||||
}
|
||||
|
||||
static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
int16_t *pTxPowerIndexOffset)
|
||||
@ -746,7 +823,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
|
||||
#define SM_PDGAIN_B(x, y) \
|
||||
SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
|
||||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
||||
struct cal_data_per_freq *pRawDataset;
|
||||
u8 *pCalBChans = NULL;
|
||||
@ -754,15 +831,18 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
|
||||
u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
|
||||
u16 numPiers, i, j;
|
||||
int16_t tMinCalPower;
|
||||
int16_t tMinCalPower, diff = 0;
|
||||
u16 numXpdGain, xpdMask;
|
||||
u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
|
||||
u32 reg32, regOffset, regChainOffset;
|
||||
int16_t modalIdx;
|
||||
int8_t pwr_table_offset;
|
||||
|
||||
modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
|
||||
xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
|
||||
|
||||
pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
|
||||
|
||||
if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
|
||||
AR5416_EEP_MINOR_VER_2) {
|
||||
pdGainOverlap_t2 =
|
||||
@ -842,6 +922,13 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
numXpdGain);
|
||||
}
|
||||
|
||||
diff = ath9k_change_gain_boundary_setting(ah,
|
||||
gainBoundaries,
|
||||
numXpdGain,
|
||||
pdGainOverlap_t2,
|
||||
pwr_table_offset,
|
||||
&diff);
|
||||
|
||||
if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
|
||||
if (OLC_FOR_AR9280_20_LATER) {
|
||||
REG_WRITE(ah,
|
||||
@ -862,6 +949,10 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ath9k_adjust_pdadc_values(ah, pwr_table_offset,
|
||||
diff, pdadcValues);
|
||||
|
||||
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
|
||||
for (j = 0; j < 32; j++) {
|
||||
reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
|
||||
@ -870,20 +961,20 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
((pdadcValues[4 * j + 3] & 0xFF) << 24);
|
||||
REG_WRITE(ah, regOffset, reg32);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"PDADC (%d,%4x): %4.4x %8.8x\n",
|
||||
i, regChainOffset, regOffset,
|
||||
reg32);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"PDADC: Chain %d | PDADC %3d "
|
||||
"Value %3d | PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | PDADC %3d "
|
||||
"Value %3d |\n",
|
||||
i, 4 * j, pdadcValues[4 * j],
|
||||
4 * j + 1, pdadcValues[4 * j + 1],
|
||||
4 * j + 2, pdadcValues[4 * j + 2],
|
||||
4 * j + 3,
|
||||
pdadcValues[4 * j + 3]);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"PDADC (%d,%4x): %4.4x %8.8x\n",
|
||||
i, regChainOffset, regOffset,
|
||||
reg32);
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"PDADC: Chain %d | PDADC %3d "
|
||||
"Value %3d | PDADC %3d Value %3d | "
|
||||
"PDADC %3d Value %3d | PDADC %3d "
|
||||
"Value %3d |\n",
|
||||
i, 4 * j, pdadcValues[4 * j],
|
||||
4 * j + 1, pdadcValues[4 * j + 1],
|
||||
4 * j + 2, pdadcValues[4 * j + 2],
|
||||
4 * j + 3,
|
||||
pdadcValues[4 * j + 3]);
|
||||
|
||||
regOffset += 4;
|
||||
}
|
||||
@ -1197,8 +1288,13 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
|
||||
for (i = 0; i < Ar5416RateSize; i++) {
|
||||
int8_t pwr_table_offset;
|
||||
|
||||
pwr_table_offset = ah->eep_ops->get_eeprom(ah,
|
||||
EEP_PWR_TABLE_OFFSET);
|
||||
ratesArray[i] -= pwr_table_offset * 2;
|
||||
}
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
|
||||
@ -1297,7 +1393,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
|
||||
ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
else
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
@ -1311,8 +1407,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1349,20 +1445,21 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
|
||||
{
|
||||
#define EEP_DEF_SPURCHAN \
|
||||
(ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
u16 spur_val = AR_NO_SPUR;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Getting spur idx %d is2Ghz. %d val %x\n",
|
||||
i, is2GHz, ah->config.spurchans[i][is2GHz]);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Getting spur idx %d is2Ghz. %d val %x\n",
|
||||
i, is2GHz, ah->config.spurchans[i][is2GHz]);
|
||||
|
||||
switch (ah->config.spurmode) {
|
||||
case SPUR_DISABLE:
|
||||
break;
|
||||
case SPUR_ENABLE_IOCTL:
|
||||
spur_val = ah->config.spurchans[i][is2GHz];
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Getting spur val from new loc. %d\n", spur_val);
|
||||
ath_print(common, ATH_DBG_ANI,
|
||||
"Getting spur val from new loc. %d\n", spur_val);
|
||||
break;
|
||||
case SPUR_ENABLE_EEPROM:
|
||||
spur_val = EEP_DEF_SPURCHAN;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,17 +27,24 @@
|
||||
#include "calib.h"
|
||||
#include "reg.h"
|
||||
#include "phy.h"
|
||||
#include "btcoex.h"
|
||||
|
||||
#include "../regd.h"
|
||||
#include "../debug.h"
|
||||
|
||||
#define ATHEROS_VENDOR_ID 0x168c
|
||||
|
||||
#define AR5416_DEVID_PCI 0x0023
|
||||
#define AR5416_DEVID_PCIE 0x0024
|
||||
#define AR9160_DEVID_PCI 0x0027
|
||||
#define AR9280_DEVID_PCI 0x0029
|
||||
#define AR9280_DEVID_PCIE 0x002a
|
||||
#define AR9285_DEVID_PCIE 0x002b
|
||||
|
||||
#define AR5416_AR9100_DEVID 0x000b
|
||||
|
||||
#define AR9271_USB 0x9271
|
||||
|
||||
#define AR_SUBVENDOR_ID_NOG 0x0e11
|
||||
#define AR_SUBVENDOR_ID_NEW_A 0x7065
|
||||
#define AR5416_MAGIC 0x19641014
|
||||
@ -49,9 +56,18 @@
|
||||
#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa
|
||||
#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab
|
||||
|
||||
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
|
||||
|
||||
#define ATH_DEFAULT_NOISE_FLOOR -95
|
||||
|
||||
#define ATH9K_RSSI_BAD 0x80
|
||||
|
||||
/* Register read/write primitives */
|
||||
#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
|
||||
#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
|
||||
#define REG_WRITE(_ah, _reg, _val) \
|
||||
ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
|
||||
|
||||
#define REG_READ(_ah, _reg) \
|
||||
ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_S) & _f)
|
||||
#define MS(_v, _f) (((_v) & _f) >> _f##_S)
|
||||
@ -91,7 +107,7 @@
|
||||
#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
|
||||
|
||||
#define BASE_ACTIVATE_DELAY 100
|
||||
#define RTC_PLL_SETTLE_DELAY 1000
|
||||
#define RTC_PLL_SETTLE_DELAY 100
|
||||
#define COEF_SCALE_S 24
|
||||
#define HT40_CHANNEL_CENTER_SHIFT 10
|
||||
|
||||
@ -433,7 +449,8 @@ struct ath_gen_timer_table {
|
||||
};
|
||||
|
||||
struct ath_hw {
|
||||
struct ath_softc *ah_sc;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ath_common common;
|
||||
struct ath9k_hw_version hw_version;
|
||||
struct ath9k_ops_config config;
|
||||
struct ath9k_hw_capabilities caps;
|
||||
@ -450,7 +467,6 @@ struct ath_hw {
|
||||
|
||||
bool sw_mgmt_crypto;
|
||||
bool is_pciexpress;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
u16 tx_trig_level;
|
||||
u16 rfsilent;
|
||||
u32 rfkill_gpio;
|
||||
@ -553,8 +569,10 @@ struct ath_hw {
|
||||
int firpwr[5];
|
||||
enum ath9k_ani_cmd ani_function;
|
||||
|
||||
/* Bluetooth coexistance */
|
||||
struct ath_btcoex_hw btcoex_hw;
|
||||
|
||||
u32 intr_txqs;
|
||||
enum ath9k_ht_extprotspacing extprotspacing;
|
||||
u8 txchainmask;
|
||||
u8 rxchainmask;
|
||||
|
||||
@ -578,12 +596,24 @@ struct ath_hw {
|
||||
struct ar5416IniArray iniModesAdditional;
|
||||
struct ar5416IniArray iniModesRxGain;
|
||||
struct ar5416IniArray iniModesTxGain;
|
||||
struct ar5416IniArray iniCckfirNormal;
|
||||
struct ar5416IniArray iniCckfirJapan2484;
|
||||
|
||||
u32 intr_gen_timer_trigger;
|
||||
u32 intr_gen_timer_thresh;
|
||||
struct ath_gen_timer_table hw_gen_timers;
|
||||
};
|
||||
|
||||
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
||||
{
|
||||
return &ah->common;
|
||||
}
|
||||
|
||||
static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
|
||||
{
|
||||
return &(ath9k_hw_common(ah)->regulatory);
|
||||
}
|
||||
|
||||
/* Initialization, Detach, Reset */
|
||||
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
|
||||
void ath9k_hw_detach(struct ath_hw *ah);
|
||||
@ -637,19 +667,20 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
|
||||
void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac);
|
||||
void ath9k_hw_setopmode(struct ath_hw *ah);
|
||||
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
|
||||
void ath9k_hw_setbssidmask(struct ath_softc *sc);
|
||||
void ath9k_hw_write_associd(struct ath_softc *sc);
|
||||
void ath9k_hw_setbssidmask(struct ath_hw *ah);
|
||||
void ath9k_hw_write_associd(struct ath_hw *ah);
|
||||
u64 ath9k_hw_gettsf64(struct ath_hw *ah);
|
||||
void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
|
||||
void ath9k_hw_reset_tsf(struct ath_hw *ah);
|
||||
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
|
||||
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hw *ah);
|
||||
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
|
||||
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
|
||||
const struct ath9k_beacon_state *bs);
|
||||
bool ath9k_hw_setpower(struct ath_hw *ah,
|
||||
enum ath9k_power_mode mode);
|
||||
|
||||
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
|
||||
|
||||
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off);
|
||||
|
||||
/* Interrupt Handling */
|
||||
@ -663,9 +694,12 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
|
||||
void (*overflow)(void *),
|
||||
void *arg,
|
||||
u8 timer_index);
|
||||
void ath_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer,
|
||||
u32 timer_next, u32 timer_period);
|
||||
void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
|
||||
void ath9k_hw_gen_timer_start(struct ath_hw *ah,
|
||||
struct ath_gen_timer *timer,
|
||||
u32 timer_next,
|
||||
u32 timer_period);
|
||||
void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
|
||||
|
||||
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
|
||||
void ath_gen_timer_isr(struct ath_hw *hw);
|
||||
u32 ath9k_hw_gettsf32(struct ath_hw *ah);
|
||||
@ -674,5 +708,4 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah);
|
||||
#define ATH_PCIE_CAP_LINK_L0S 1
|
||||
#define ATH_PCIE_CAP_LINK_L1 2
|
||||
|
||||
void ath_pcie_aspm_disable(struct ath_softc *sc);
|
||||
#endif
|
||||
|
@ -21,6 +21,8 @@ static const u32 ar5416Modes[][6] = {
|
||||
{ 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
|
||||
{ 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
|
||||
{ 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
|
||||
{ 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
|
||||
{ 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a },
|
||||
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
|
||||
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
|
||||
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
@ -31,11 +33,11 @@ static const u32 ar5416Modes[][6] = {
|
||||
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
|
||||
{ 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de },
|
||||
{ 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de },
|
||||
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
|
||||
{ 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
|
||||
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
|
||||
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
|
||||
@ -46,10 +48,10 @@ static const u32 ar5416Modes[][6] = {
|
||||
{ 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
|
||||
{ 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
|
||||
{ 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
|
||||
{ 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
|
||||
{ 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
|
||||
{ 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
|
||||
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
|
||||
{ 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
|
||||
{ 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c },
|
||||
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
|
||||
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
|
||||
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
@ -199,7 +201,6 @@ static const u32 ar5416Common[][2] = {
|
||||
{ 0x00008110, 0x00000168 },
|
||||
{ 0x00008118, 0x000100aa },
|
||||
{ 0x0000811c, 0x00003210 },
|
||||
{ 0x00008120, 0x08f04800 },
|
||||
{ 0x00008124, 0x00000000 },
|
||||
{ 0x00008128, 0x00000000 },
|
||||
{ 0x0000812c, 0x00000000 },
|
||||
@ -215,7 +216,6 @@ static const u32 ar5416Common[][2] = {
|
||||
{ 0x00008178, 0x00000100 },
|
||||
{ 0x0000817c, 0x00000000 },
|
||||
{ 0x000081c4, 0x00000000 },
|
||||
{ 0x000081d0, 0x00003210 },
|
||||
{ 0x000081ec, 0x00000000 },
|
||||
{ 0x000081f0, 0x00000000 },
|
||||
{ 0x000081f4, 0x00000000 },
|
||||
@ -246,6 +246,7 @@ static const u32 ar5416Common[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8000010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
@ -406,9 +407,9 @@ static const u32 ar5416Common[][2] = {
|
||||
{ 0x0000a25c, 0x0f0f0f01 },
|
||||
{ 0x0000a260, 0xdfa91f01 },
|
||||
{ 0x0000a268, 0x00000000 },
|
||||
{ 0x0000a26c, 0x0ebae9c6 },
|
||||
{ 0x0000b26c, 0x0ebae9c6 },
|
||||
{ 0x0000c26c, 0x0ebae9c6 },
|
||||
{ 0x0000a26c, 0x0e79e5c6 },
|
||||
{ 0x0000b26c, 0x0e79e5c6 },
|
||||
{ 0x0000c26c, 0x0e79e5c6 },
|
||||
{ 0x0000d270, 0x00820820 },
|
||||
{ 0x0000a278, 0x1ce739ce },
|
||||
{ 0x0000a27c, 0x051701ce },
|
||||
@ -2551,26 +2552,27 @@ static const u32 ar9280Modes_9280_2[][6] = {
|
||||
{ 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
|
||||
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
|
||||
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
|
||||
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e },
|
||||
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
|
||||
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
|
||||
{ 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
|
||||
{ 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
|
||||
{ 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
|
||||
{ 0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
|
||||
{ 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e },
|
||||
{ 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
|
||||
{ 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
|
||||
{ 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
|
||||
{ 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
|
||||
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
|
||||
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
|
||||
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016 },
|
||||
{ 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 },
|
||||
{ 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
|
||||
{ 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
|
||||
{ 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
|
||||
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
|
||||
@ -2585,8 +2587,10 @@ static const u32 ar9280Modes_9280_2[][6] = {
|
||||
{ 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
|
||||
{ 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
|
||||
{ 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
|
||||
{ 0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000 },
|
||||
{ 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
|
||||
{ 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
|
||||
{ 0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000 },
|
||||
{ 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
|
||||
};
|
||||
@ -2813,7 +2817,6 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x00009958, 0x2108ecff },
|
||||
{ 0x00009940, 0x14750604 },
|
||||
{ 0x0000c95c, 0x004b6a8e },
|
||||
{ 0x0000c968, 0x000003ce },
|
||||
{ 0x00009970, 0x190fb515 },
|
||||
{ 0x00009974, 0x00000000 },
|
||||
{ 0x00009978, 0x00000001 },
|
||||
@ -2849,7 +2852,6 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x0000a22c, 0x233f7180 },
|
||||
{ 0x0000a234, 0x20202020 },
|
||||
{ 0x0000a238, 0x20202020 },
|
||||
{ 0x0000a23c, 0x13c88000 },
|
||||
{ 0x0000a240, 0x38490a20 },
|
||||
{ 0x0000a244, 0x00007bb6 },
|
||||
{ 0x0000a248, 0x0fff3ffc },
|
||||
@ -2859,8 +2861,8 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x0000a25c, 0x0f0f0f01 },
|
||||
{ 0x0000a260, 0xdfa91f01 },
|
||||
{ 0x0000a268, 0x00000000 },
|
||||
{ 0x0000a26c, 0x0ebae9c6 },
|
||||
{ 0x0000b26c, 0x0ebae9c6 },
|
||||
{ 0x0000a26c, 0x0e79e5c6 },
|
||||
{ 0x0000b26c, 0x0e79e5c6 },
|
||||
{ 0x0000d270, 0x00820820 },
|
||||
{ 0x0000a278, 0x1ce739ce },
|
||||
{ 0x0000d35c, 0x07ffffef },
|
||||
@ -2874,7 +2876,6 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x0000d37c, 0x7fffffe2 },
|
||||
{ 0x0000d380, 0x7f3c7bba },
|
||||
{ 0x0000d384, 0xf3307ff0 },
|
||||
{ 0x0000a388, 0x0c000000 },
|
||||
{ 0x0000a38c, 0x20202020 },
|
||||
{ 0x0000a390, 0x20202020 },
|
||||
{ 0x0000a394, 0x1ce739ce },
|
||||
@ -2940,7 +2941,7 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
|
||||
{ 0x0000801c, 0x148ec02b, 0x148ec057 },
|
||||
{ 0x00008318, 0x000044c0, 0x00008980 },
|
||||
{ 0x00009820, 0x02020200, 0x02020200 },
|
||||
{ 0x00009824, 0x00000f0f, 0x00000f0f },
|
||||
{ 0x00009824, 0x01000f0f, 0x01000f0f },
|
||||
{ 0x00009828, 0x0b020001, 0x0b020001 },
|
||||
{ 0x00009834, 0x00000f0f, 0x00000f0f },
|
||||
{ 0x00009844, 0x03721821, 0x03721821 },
|
||||
@ -3348,6 +3349,8 @@ static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
|
||||
{ 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
|
||||
{ 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
|
||||
{ 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
|
||||
@ -3376,11 +3379,11 @@ static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
|
||||
{ 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
|
||||
{ 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
|
||||
{ 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
|
||||
{ 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
|
||||
{ 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
|
||||
};
|
||||
|
||||
static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
|
||||
{ 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
|
||||
{ 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
|
||||
{ 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
|
||||
@ -3409,8 +3412,6 @@ static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
|
||||
{ 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
|
||||
{ 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
|
||||
{ 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
|
||||
{ 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
|
||||
{ 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
|
||||
};
|
||||
|
||||
static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
|
||||
@ -5918,9 +5919,6 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = {
|
||||
{ 0x000099ec, 0x0cc80caa },
|
||||
{ 0x000099f0, 0x00000000 },
|
||||
{ 0x000099fc, 0x00001042 },
|
||||
{ 0x0000a1f4, 0x00fffeff },
|
||||
{ 0x0000a1f8, 0x00f5f9ff },
|
||||
{ 0x0000a1fc, 0xb79f6427 },
|
||||
{ 0x0000a208, 0x803e4788 },
|
||||
{ 0x0000a210, 0x4080a333 },
|
||||
{ 0x0000a214, 0x40206c10 },
|
||||
@ -5980,7 +5978,7 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = {
|
||||
{ 0x0000b3f4, 0x00000000 },
|
||||
{ 0x0000a7d8, 0x000003f1 },
|
||||
{ 0x00007800, 0x00000800 },
|
||||
{ 0x00007804, 0x6c35ffc2 },
|
||||
{ 0x00007804, 0x6c35ffd2 },
|
||||
{ 0x00007808, 0x6db6c000 },
|
||||
{ 0x0000780c, 0x6db6cb30 },
|
||||
{ 0x00007810, 0x6db6cb6c },
|
||||
@ -6000,7 +5998,7 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = {
|
||||
{ 0x00007848, 0x934934a8 },
|
||||
{ 0x00007850, 0x00000000 },
|
||||
{ 0x00007854, 0x00000800 },
|
||||
{ 0x00007858, 0x6c35ffc2 },
|
||||
{ 0x00007858, 0x6c35ffd2 },
|
||||
{ 0x0000785c, 0x6db6c000 },
|
||||
{ 0x00007860, 0x6db6cb30 },
|
||||
{ 0x00007864, 0x6db6cb6c },
|
||||
@ -6027,6 +6025,22 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = {
|
||||
{ 0x000078b8, 0x2a850160 },
|
||||
};
|
||||
|
||||
/*
|
||||
* For Japanese regulatory requirements, 2484 MHz requires the following three
|
||||
* registers be programmed differently from the channel between 2412 and 2472 MHz.
|
||||
*/
|
||||
static const u_int32_t ar9287Common_normal_cck_fir_coeff_92871_1[][2] = {
|
||||
{ 0x0000a1f4, 0x00fffeff },
|
||||
{ 0x0000a1f8, 0x00f5f9ff },
|
||||
{ 0x0000a1fc, 0xb79f6427 },
|
||||
};
|
||||
|
||||
static const u_int32_t ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = {
|
||||
{ 0x0000a1f4, 0x00000000 },
|
||||
{ 0x0000a1f8, 0xefff0301 },
|
||||
{ 0x0000a1fc, 0xca9228ee },
|
||||
};
|
||||
|
||||
static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = {
|
||||
/* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
|
||||
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
|
@ -14,16 +14,16 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
|
||||
struct ath9k_tx_queue_info *qi)
|
||||
{
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
|
||||
"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
|
||||
ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
|
||||
ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
|
||||
ah->txurn_interrupt_mask);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
|
||||
"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
|
||||
ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
|
||||
ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
|
||||
ah->txurn_interrupt_mask);
|
||||
|
||||
REG_WRITE(ah, AR_IMR_S0,
|
||||
SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
|
||||
@ -39,17 +39,21 @@ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
return REG_READ(ah, AR_QTXDP(q));
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_gettxbuf);
|
||||
|
||||
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
|
||||
{
|
||||
REG_WRITE(ah, AR_QTXDP(q), txdp);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_puttxbuf);
|
||||
|
||||
void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE,
|
||||
"Enable TXE on queue: %u\n", q);
|
||||
REG_WRITE(ah, AR_Q_TXE, 1 << q);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_txstart);
|
||||
|
||||
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
@ -64,6 +68,7 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
|
||||
|
||||
return npend;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_numtxpending);
|
||||
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
|
||||
{
|
||||
@ -93,27 +98,28 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
|
||||
|
||||
return newLevel != curLevel;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
|
||||
|
||||
bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
|
||||
#define ATH9K_TIME_QUANTUM 100 /* usec */
|
||||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
u32 tsfLow, j, wait;
|
||||
u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
|
||||
|
||||
if (q >= pCap->total_queues) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
|
||||
"invalid queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
|
||||
"invalid queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
|
||||
"inactive queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, "
|
||||
"inactive queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -126,9 +132,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
}
|
||||
|
||||
if (ath9k_hw_numtxpending(ah, q)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
|
||||
"%s: Num of pending TX Frames %d on Q %d\n",
|
||||
__func__, ath9k_hw_numtxpending(ah, q), q);
|
||||
ath_print(common, ATH_DBG_QUEUE,
|
||||
"%s: Num of pending TX Frames %d on Q %d\n",
|
||||
__func__, ath9k_hw_numtxpending(ah, q), q);
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
tsfLow = REG_READ(ah, AR_TSF_L32);
|
||||
@ -142,9 +148,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
|
||||
break;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
|
||||
"TSF has moved while trying to set "
|
||||
"quiet time TSF: 0x%08x\n", tsfLow);
|
||||
ath_print(common, ATH_DBG_QUEUE,
|
||||
"TSF has moved while trying to set "
|
||||
"quiet time TSF: 0x%08x\n", tsfLow);
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
@ -155,9 +161,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
wait = wait_time;
|
||||
while (ath9k_hw_numtxpending(ah, q)) {
|
||||
if ((--wait) == 0) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
|
||||
"Failed to stop TX DMA in 100 "
|
||||
"msec after killing last frame\n");
|
||||
ath_print(common, ATH_DBG_QUEUE,
|
||||
"Failed to stop TX DMA in 100 "
|
||||
"msec after killing last frame\n");
|
||||
break;
|
||||
}
|
||||
udelay(ATH9K_TIME_QUANTUM);
|
||||
@ -172,6 +178,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
#undef ATH9K_TX_STOP_DMA_TIMEOUT
|
||||
#undef ATH9K_TIME_QUANTUM
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_stoptxdma);
|
||||
|
||||
void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 segLen, bool firstSeg,
|
||||
@ -198,6 +205,7 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
|
||||
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_filltxdesc);
|
||||
|
||||
void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
|
||||
{
|
||||
@ -209,6 +217,7 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
|
||||
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
|
||||
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
|
||||
|
||||
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
|
||||
{
|
||||
@ -284,6 +293,7 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_txprocdesc);
|
||||
|
||||
void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
|
||||
@ -319,6 +329,7 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
ads->ds_ctl11 = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set11n_txdesc);
|
||||
|
||||
void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
|
||||
struct ath_desc *lastds,
|
||||
@ -374,6 +385,7 @@ void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
|
||||
last_ads->ds_ctl2 = ads->ds_ctl2;
|
||||
last_ads->ds_ctl3 = ads->ds_ctl3;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario);
|
||||
|
||||
void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 aggrLen)
|
||||
@ -384,6 +396,7 @@ void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
|
||||
ads->ds_ctl6 &= ~AR_AggrLen;
|
||||
ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first);
|
||||
|
||||
void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 numDelims)
|
||||
@ -398,6 +411,7 @@ void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
|
||||
ctl6 |= SM(numDelims, AR_PadDelim);
|
||||
ads->ds_ctl6 = ctl6;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle);
|
||||
|
||||
void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
|
||||
{
|
||||
@ -407,6 +421,7 @@ void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
|
||||
ads->ds_ctl1 &= ~AR_MoreAggr;
|
||||
ads->ds_ctl6 &= ~AR_PadDelim;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last);
|
||||
|
||||
void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
|
||||
{
|
||||
@ -414,6 +429,7 @@ void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
|
||||
|
||||
ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_clr11n_aggr);
|
||||
|
||||
void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 burstDuration)
|
||||
@ -423,6 +439,7 @@ void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
|
||||
ads->ds_ctl2 &= ~AR_BurstDur;
|
||||
ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set11n_burstduration);
|
||||
|
||||
void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 vmf)
|
||||
@ -440,28 +457,30 @@ void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
|
||||
*txqs &= ah->intr_txqs;
|
||||
ah->intr_txqs &= ~(*txqs);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs);
|
||||
|
||||
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
const struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
u32 cw;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
|
||||
if (q >= pCap->total_queues) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
|
||||
"invalid queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, "
|
||||
"invalid queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
|
||||
"inactive queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, "
|
||||
"inactive queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
|
||||
|
||||
qi->tqi_ver = qinfo->tqi_ver;
|
||||
qi->tqi_subtype = qinfo->tqi_subtype;
|
||||
@ -510,23 +529,25 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set_txq_props);
|
||||
|
||||
bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
|
||||
struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
|
||||
if (q >= pCap->total_queues) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
|
||||
"invalid queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, "
|
||||
"invalid queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
|
||||
"inactive queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, "
|
||||
"inactive queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -547,10 +568,12 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_get_txq_props);
|
||||
|
||||
int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
|
||||
const struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
int q;
|
||||
@ -574,23 +597,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
|
||||
ATH9K_TX_QUEUE_INACTIVE)
|
||||
break;
|
||||
if (q == pCap->total_queues) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"No available TX queue\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"No available TX queue\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n",
|
||||
type);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Invalid TX queue type: %u\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"TX queue: %u already active\n", q);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"TX queue: %u already active\n", q);
|
||||
return -1;
|
||||
}
|
||||
memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
|
||||
@ -613,25 +636,27 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
|
||||
|
||||
return q;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
|
||||
|
||||
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
|
||||
if (q >= pCap->total_queues) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
|
||||
"invalid queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Release TXQ, "
|
||||
"invalid queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
|
||||
"inactive queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Release TXQ, "
|
||||
"inactive queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
|
||||
|
||||
qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
|
||||
ah->txok_interrupt_mask &= ~(1 << q);
|
||||
@ -643,28 +668,30 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_releasetxqueue);
|
||||
|
||||
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ath9k_tx_queue_info *qi;
|
||||
u32 cwMin, chanCwMin, value;
|
||||
|
||||
if (q >= pCap->total_queues) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
|
||||
"invalid queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, "
|
||||
"invalid queue: %u\n", q);
|
||||
return false;
|
||||
}
|
||||
|
||||
qi = &ah->txq[q];
|
||||
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
|
||||
"inactive queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, "
|
||||
"inactive queue: %u\n", q);
|
||||
return true;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
|
||||
ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
|
||||
|
||||
if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
|
||||
if (chan && IS_CHAN_B(chan))
|
||||
@ -799,6 +826,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
|
||||
|
||||
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 pa, struct ath_desc *nds, u64 tsf)
|
||||
@ -880,6 +908,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
|
||||
|
||||
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
u32 size, u32 flags)
|
||||
@ -895,6 +924,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
memset(&(ads->u), 0, sizeof(ads->u));
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
|
||||
|
||||
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
|
||||
{
|
||||
@ -911,8 +941,9 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
|
||||
AR_DIAG_RX_ABORT));
|
||||
|
||||
reg = REG_READ(ah, AR_OBS_BUS_1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"RX failed to go idle in 10 ms RXSM=0x%x\n", reg);
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
|
||||
"RX failed to go idle in 10 ms RXSM=0x%x\n",
|
||||
reg);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -923,16 +954,19 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_setrxabort);
|
||||
|
||||
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
|
||||
{
|
||||
REG_WRITE(ah, AR_RXDP, rxdp);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_putrxbuf);
|
||||
|
||||
void ath9k_hw_rxena(struct ath_hw *ah)
|
||||
{
|
||||
REG_WRITE(ah, AR_CR, AR_CR_RXE);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_rxena);
|
||||
|
||||
void ath9k_hw_startpcureceive(struct ath_hw *ah)
|
||||
{
|
||||
@ -942,6 +976,7 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah)
|
||||
|
||||
REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_startpcureceive);
|
||||
|
||||
void ath9k_hw_stoppcurecv(struct ath_hw *ah)
|
||||
{
|
||||
@ -949,12 +984,13 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah)
|
||||
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_stoppcurecv);
|
||||
|
||||
bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
|
||||
{
|
||||
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
|
||||
#define AH_RX_TIME_QUANTUM 100 /* usec */
|
||||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int i;
|
||||
|
||||
REG_WRITE(ah, AR_CR, AR_CR_RXD);
|
||||
@ -967,12 +1003,12 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"DMA failed to stop in %d ms "
|
||||
"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
|
||||
AH_RX_STOP_DMA_TIMEOUT / 1000,
|
||||
REG_READ(ah, AR_CR),
|
||||
REG_READ(ah, AR_DIAG_SW));
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"DMA failed to stop in %d ms "
|
||||
"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
|
||||
AH_RX_STOP_DMA_TIMEOUT / 1000,
|
||||
REG_READ(ah, AR_CR),
|
||||
REG_READ(ah, AR_DIAG_SW));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
@ -981,3 +1017,17 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
|
||||
#undef AH_RX_TIME_QUANTUM
|
||||
#undef AH_RX_STOP_DMA_TIMEOUT
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_stopdmarecv);
|
||||
|
||||
int ath9k_hw_beaconq_setup(struct ath_hw *ah)
|
||||
{
|
||||
struct ath9k_tx_queue_info qi;
|
||||
|
||||
memset(&qi, 0, sizeof(qi));
|
||||
qi.tqi_aifs = 1;
|
||||
qi.tqi_cwmin = 0;
|
||||
qi.tqi_cwmax = 0;
|
||||
/* NB: don't enable any interrupts */
|
||||
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
|
||||
|
@ -614,16 +614,6 @@ enum ath9k_cipher {
|
||||
ATH9K_CIPHER_MIC = 127
|
||||
};
|
||||
|
||||
enum ath9k_ht_macmode {
|
||||
ATH9K_HT_MACMODE_20 = 0,
|
||||
ATH9K_HT_MACMODE_2040 = 1,
|
||||
};
|
||||
|
||||
enum ath9k_ht_extprotspacing {
|
||||
ATH9K_HT_EXTPROTSPACING_20 = 0,
|
||||
ATH9K_HT_EXTPROTSPACING_25 = 1,
|
||||
};
|
||||
|
||||
struct ath_hw;
|
||||
struct ath9k_channel;
|
||||
struct ath_rate_table;
|
||||
@ -677,5 +667,6 @@ void ath9k_hw_rxena(struct ath_hw *ah);
|
||||
void ath9k_hw_startpcureceive(struct ath_hw *ah);
|
||||
void ath9k_hw_stoppcurecv(struct ath_hw *ah);
|
||||
bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
|
||||
int ath9k_hw_beaconq_setup(struct ath_hw *ah);
|
||||
|
||||
#endif /* MAC_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,8 +31,9 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
|
||||
};
|
||||
|
||||
/* return bus cachesize in 4B word units */
|
||||
static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
u8 u8tmp;
|
||||
|
||||
pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp);
|
||||
@ -48,8 +49,9 @@ static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
|
||||
}
|
||||
|
||||
static void ath_pci_cleanup(struct ath_softc *sc)
|
||||
static void ath_pci_cleanup(struct ath_common *common)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
struct pci_dev *pdev = to_pci_dev(sc->dev);
|
||||
|
||||
pci_iounmap(pdev, sc->mem);
|
||||
@ -57,9 +59,11 @@ static void ath_pci_cleanup(struct ath_softc *sc)
|
||||
pci_release_region(pdev, 0);
|
||||
}
|
||||
|
||||
static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||
static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
|
||||
common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
|
||||
|
||||
if (!ath9k_hw_wait(ah,
|
||||
AR_EEPROM_STATUS_DATA,
|
||||
@ -69,16 +73,34 @@ static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
|
||||
*data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
|
||||
AR_EEPROM_STATUS_DATA_VAL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct ath_bus_ops ath_pci_bus_ops = {
|
||||
/*
|
||||
* Bluetooth coexistance requires disabling ASPM.
|
||||
*/
|
||||
static void ath_pci_bt_coex_prep(struct ath_common *common)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
struct pci_dev *pdev = to_pci_dev(sc->dev);
|
||||
u8 aspm;
|
||||
|
||||
if (!pdev->is_pcie)
|
||||
return;
|
||||
|
||||
pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
|
||||
aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);
|
||||
pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
|
||||
}
|
||||
|
||||
const static struct ath_bus_ops ath_pci_bus_ops = {
|
||||
.read_cachesize = ath_pci_read_cachesize,
|
||||
.cleanup = ath_pci_cleanup,
|
||||
.eeprom_read = ath_pci_eeprom_read,
|
||||
.bt_coex_prep = ath_pci_bt_coex_prep,
|
||||
};
|
||||
|
||||
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
@ -177,10 +199,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
sc->hw = hw;
|
||||
sc->dev = &pdev->dev;
|
||||
sc->mem = mem;
|
||||
sc->bus_ops = &ath_pci_bus_ops;
|
||||
|
||||
pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
|
||||
ret = ath_init_device(id->device, sc, subsysid);
|
||||
ret = ath_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize device\n");
|
||||
goto bad3;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "hw.h"
|
||||
|
||||
void
|
||||
ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex,
|
||||
@ -26,6 +26,7 @@ ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex,
|
||||
bool
|
||||
ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 channelSel = 0;
|
||||
u32 bModeSynth = 0;
|
||||
u32 aModeRefSel = 0;
|
||||
@ -46,8 +47,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
channelSel = ((freq - 704) * 2 - 3040) / 10;
|
||||
bModeSynth = 1;
|
||||
} else {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Invalid channel %u MHz\n", freq);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Invalid channel %u MHz\n", freq);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -79,8 +80,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
|
||||
aModeRefSel = ath9k_hw_reverse_bits(1, 2);
|
||||
} else {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Invalid channel %u MHz\n", freq);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Invalid channel %u MHz\n", freq);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -112,20 +113,31 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
|
||||
|
||||
if (freq < 4800) {
|
||||
u32 txctl;
|
||||
int regWrites = 0;
|
||||
|
||||
bMode = 1;
|
||||
fracMode = 1;
|
||||
aModeRefSel = 0;
|
||||
channelSel = (freq * 0x10000) / 15;
|
||||
|
||||
txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
|
||||
if (freq == 2484) {
|
||||
|
||||
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
|
||||
txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
|
||||
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||
if (freq == 2484) {
|
||||
REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
|
||||
1, regWrites);
|
||||
} else {
|
||||
REG_WRITE_ARRAY(&ah->iniCckfirNormal,
|
||||
1, regWrites);
|
||||
}
|
||||
} else {
|
||||
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
|
||||
txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
|
||||
txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
|
||||
if (freq == 2484) {
|
||||
/* Enable channel spreading for channel 14 */
|
||||
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
|
||||
txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
|
||||
} else {
|
||||
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
|
||||
txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bMode = 0;
|
||||
@ -285,6 +297,8 @@ ath9k_hw_rf_free(struct ath_hw *ah)
|
||||
|
||||
bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
ah->analogBank0Data =
|
||||
kzalloc((sizeof(u32) *
|
||||
@ -315,8 +329,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
|
||||
|| ah->analogBank6Data == NULL
|
||||
|| ah->analogBank6TPCData == NULL
|
||||
|| ah->analogBank7Data == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Cannot allocate RF banks\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Cannot allocate RF banks\n");
|
||||
*status = -ENOMEM;
|
||||
return false;
|
||||
}
|
||||
@ -326,8 +340,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
|
||||
ah->iniAddac.ia_rows *
|
||||
ah->iniAddac.ia_columns), GFP_KERNEL);
|
||||
if (ah->addac5416_21 == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Cannot allocate addac5416_21\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Cannot allocate addac5416_21\n");
|
||||
*status = -ENOMEM;
|
||||
return false;
|
||||
}
|
||||
@ -336,8 +350,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
|
||||
kzalloc((sizeof(u32) *
|
||||
ah->iniBank6.ia_rows), GFP_KERNEL);
|
||||
if (ah->bank6Temp == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"Cannot allocate bank6Temp\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Cannot allocate bank6Temp\n");
|
||||
*status = -ENOMEM;
|
||||
return false;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
|
||||
#define AR_PHY_FC_DYN2040_EN 0x00000004
|
||||
#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
|
||||
#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
|
||||
/* For 25 MHz channel spacing -- not used but supported by hw */
|
||||
#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
|
||||
#define AR_PHY_FC_HT_EN 0x00000040
|
||||
#define AR_PHY_FC_SHORT_GI_40 0x00000080
|
||||
|
@ -425,7 +425,7 @@ static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
|
||||
static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
|
||||
u8 index, int valid_tx_rate)
|
||||
{
|
||||
ASSERT(index <= ath_rc_priv->rate_table_size);
|
||||
BUG_ON(index > ath_rc_priv->rate_table_size);
|
||||
ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -1160,6 +1160,7 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
|
||||
bool is_cw_40)
|
||||
{
|
||||
int mode = 0;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
switch(band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
@ -1177,13 +1178,14 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
|
||||
mode = ATH9K_MODE_11NA_HT40PLUS;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n");
|
||||
ath_print(common, ATH_DBG_CONFIG, "Invalid band\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BUG_ON(mode >= ATH9K_MODE_MAX);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode);
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Choosing rate table for mode: %d\n", mode);
|
||||
return sc->hw_rate_table[mode];
|
||||
}
|
||||
|
||||
@ -1194,11 +1196,13 @@ static void ath_rc_init(struct ath_softc *sc,
|
||||
const struct ath_rate_table *rate_table)
|
||||
{
|
||||
struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
|
||||
u8 i, j, k, hi = 0, hthi = 0;
|
||||
|
||||
if (!rate_table) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Rate table not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1239,7 +1243,7 @@ static void ath_rc_init(struct ath_softc *sc,
|
||||
|
||||
ath_rc_priv->rate_table_size = hi + 1;
|
||||
ath_rc_priv->rate_max_phy = 0;
|
||||
ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
|
||||
BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
|
||||
|
||||
for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
|
||||
for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
|
||||
@ -1253,16 +1257,17 @@ static void ath_rc_init(struct ath_softc *sc,
|
||||
|
||||
ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
|
||||
}
|
||||
ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
|
||||
ASSERT(k <= RATE_TABLE_SIZE);
|
||||
BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE);
|
||||
BUG_ON(k > RATE_TABLE_SIZE);
|
||||
|
||||
ath_rc_priv->max_valid_rate = k;
|
||||
ath_rc_sort_validrates(rate_table, ath_rc_priv);
|
||||
ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
|
||||
sc->cur_rate_table = rate_table;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n",
|
||||
ath_rc_priv->ht_cap);
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"RC Initialized with capabilities: 0x%x\n",
|
||||
ath_rc_priv->ht_cap);
|
||||
}
|
||||
|
||||
static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
@ -1438,9 +1443,9 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
|
||||
oper_cw40, oper_sgi40);
|
||||
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"Operating HT Bandwidth changed to: %d\n",
|
||||
sc->hw->conf.channel_type);
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
|
||||
"Operating HT Bandwidth changed to: %d\n",
|
||||
sc->hw->conf.channel_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1463,8 +1468,8 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp
|
||||
|
||||
rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
|
||||
if (!rate_priv) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to allocate private rc structure\n");
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"Unable to allocate private rc structure\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||
|
||||
/* virtual addr of the beginning of the buffer. */
|
||||
skb = bf->bf_mpdu;
|
||||
ASSERT(skb != NULL);
|
||||
BUG_ON(skb == NULL);
|
||||
ds->ds_vdata = skb->data;
|
||||
|
||||
/* setup rx descriptors. The rx.bufsize here tells the harware
|
||||
@ -272,6 +272,8 @@ rx_next:
|
||||
static void ath_opmode_init(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
u32 rfilt, mfilt[2];
|
||||
|
||||
/* configure rx filter */
|
||||
@ -280,13 +282,13 @@ static void ath_opmode_init(struct ath_softc *sc)
|
||||
|
||||
/* configure bssid mask */
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
|
||||
ath9k_hw_setbssidmask(sc);
|
||||
ath_hw_setbssidmask(common);
|
||||
|
||||
/* configure operational mode */
|
||||
ath9k_hw_setopmode(ah);
|
||||
|
||||
/* Handle any link-level address change. */
|
||||
ath9k_hw_setmac(ah, sc->sc_ah->macaddr);
|
||||
ath9k_hw_setmac(ah, common->macaddr);
|
||||
|
||||
/* calculate and install multicast filter */
|
||||
mfilt[0] = mfilt[1] = ~0;
|
||||
@ -295,6 +297,7 @@ static void ath_opmode_init(struct ath_softc *sc)
|
||||
|
||||
int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct sk_buff *skb;
|
||||
struct ath_buf *bf;
|
||||
int error = 0;
|
||||
@ -304,23 +307,23 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
spin_lock_init(&sc->rx.rxbuflock);
|
||||
|
||||
sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
|
||||
min(sc->common.cachelsz, (u16)64));
|
||||
min(common->cachelsz, (u16)64));
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
|
||||
sc->common.cachelsz, sc->rx.bufsize);
|
||||
ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
|
||||
common->cachelsz, sc->rx.bufsize);
|
||||
|
||||
/* Initialize rx descriptors */
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
|
||||
"rx", nbufs, 1);
|
||||
if (error != 0) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"failed to allocate rx descriptors: %d\n", error);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"failed to allocate rx descriptors: %d\n", error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL);
|
||||
skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_KERNEL);
|
||||
if (skb == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
@ -334,8 +337,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on RX init\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on RX init\n");
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
@ -420,7 +423,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
|
||||
else
|
||||
rfilt |= ATH9K_RX_FILTER_BEACON;
|
||||
|
||||
if (sc->rx.rxfilter & FIF_PSPOLL)
|
||||
if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) ||
|
||||
AR_SREV_9285_10_OR_LATER(sc->sc_ah)) &&
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
|
||||
(sc->rx.rxfilter & FIF_PSPOLL))
|
||||
rfilt |= ATH9K_RX_FILTER_PSPOLL;
|
||||
|
||||
if (conf_is_ht(&sc->hw->conf))
|
||||
@ -527,20 +533,22 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
|
||||
static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
if (skb->len < 24 + 8 + 2 + 2)
|
||||
return;
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0)
|
||||
if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0)
|
||||
return; /* not from our current AP */
|
||||
|
||||
sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
|
||||
|
||||
if (sc->sc_flags & SC_OP_BEACON_SYNC) {
|
||||
sc->sc_flags &= ~SC_OP_BEACON_SYNC;
|
||||
DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on "
|
||||
"timestamp from the AP\n");
|
||||
ath_print(common, ATH_DBG_PS,
|
||||
"Reconfigure Beacon timers based on "
|
||||
"timestamp from the AP\n");
|
||||
ath_beacon_config(sc, NULL);
|
||||
}
|
||||
|
||||
@ -552,8 +560,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
|
||||
* a backup trigger for returning into NETWORK SLEEP state,
|
||||
* so we are waiting for it as well.
|
||||
*/
|
||||
DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating "
|
||||
"buffered broadcast/multicast frame(s)\n");
|
||||
ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating "
|
||||
"buffered broadcast/multicast frame(s)\n");
|
||||
sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON;
|
||||
return;
|
||||
}
|
||||
@ -565,13 +573,15 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
|
||||
* been delivered.
|
||||
*/
|
||||
sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB;
|
||||
DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n");
|
||||
ath_print(common, ATH_DBG_PS,
|
||||
"PS wait for CAB frames timed out\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
@ -589,14 +599,15 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
|
||||
* point.
|
||||
*/
|
||||
sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB;
|
||||
DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to "
|
||||
"sleep\n");
|
||||
ath_print(common, ATH_DBG_PS,
|
||||
"All PS CAB frames received, back to sleep\n");
|
||||
} else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) &&
|
||||
!is_multicast_ether_addr(hdr->addr1) &&
|
||||
!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA;
|
||||
DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
|
||||
"received PS-Poll data (0x%x)\n",
|
||||
ath_print(common, ATH_DBG_PS,
|
||||
"Going back to sleep after having received "
|
||||
"PS-Poll data (0x%x)\n",
|
||||
sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
|
||||
SC_OP_WAIT_FOR_CAB |
|
||||
SC_OP_WAIT_FOR_PSPOLL_DATA |
|
||||
@ -651,6 +662,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
struct sk_buff *skb = NULL, *requeue_skb;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padsize, retval;
|
||||
bool decrypt_error = false;
|
||||
@ -749,7 +761,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
|
||||
/* Ensure we always have an skb to requeue once we are done
|
||||
* processing the current buffer's skb */
|
||||
requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC);
|
||||
requeue_skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_ATOMIC);
|
||||
|
||||
/* If there is no memory we ignore the current RX'd frame,
|
||||
* tell hardware it can give us a new frame using the old
|
||||
@ -811,8 +823,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(requeue_skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on RX\n");
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on RX\n");
|
||||
ath_rx_send_to_mac80211(sc, skb, &rx_status);
|
||||
break;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef REG_H
|
||||
#define REG_H
|
||||
|
||||
#include "../reg.h"
|
||||
|
||||
#define AR_CR 0x0008
|
||||
#define AR_CR_RXE 0x00000004
|
||||
#define AR_CR_RXD 0x00000020
|
||||
@ -1421,9 +1423,6 @@ enum {
|
||||
#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000
|
||||
#define AR_SLEEP2_BEACON_TIMEOUT_S 21
|
||||
|
||||
#define AR_BSSMSKL 0x80e0
|
||||
#define AR_BSSMSKU 0x80e4
|
||||
|
||||
#define AR_TPC 0x80e8
|
||||
#define AR_TPC_ACK 0x0000003f
|
||||
#define AR_TPC_ACK_S 0x00
|
||||
|
@ -40,6 +40,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath9k_vif_iter_data iter_data;
|
||||
int i, j;
|
||||
u8 mask[ETH_ALEN];
|
||||
@ -51,7 +52,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
|
||||
*/
|
||||
iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
|
||||
if (iter_data.addr) {
|
||||
memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN);
|
||||
memcpy(iter_data.addr, common->macaddr, ETH_ALEN);
|
||||
iter_data.count = 1;
|
||||
} else
|
||||
iter_data.count = 0;
|
||||
@ -86,20 +87,21 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
|
||||
kfree(iter_data.addr);
|
||||
|
||||
/* Invert the mask and configure hardware */
|
||||
sc->bssidmask[0] = ~mask[0];
|
||||
sc->bssidmask[1] = ~mask[1];
|
||||
sc->bssidmask[2] = ~mask[2];
|
||||
sc->bssidmask[3] = ~mask[3];
|
||||
sc->bssidmask[4] = ~mask[4];
|
||||
sc->bssidmask[5] = ~mask[5];
|
||||
common->bssidmask[0] = ~mask[0];
|
||||
common->bssidmask[1] = ~mask[1];
|
||||
common->bssidmask[2] = ~mask[2];
|
||||
common->bssidmask[3] = ~mask[3];
|
||||
common->bssidmask[4] = ~mask[4];
|
||||
common->bssidmask[5] = ~mask[5];
|
||||
|
||||
ath9k_hw_setbssidmask(sc);
|
||||
ath_hw_setbssidmask(common);
|
||||
}
|
||||
|
||||
int ath9k_wiphy_add(struct ath_softc *sc)
|
||||
{
|
||||
int i, error;
|
||||
struct ath_wiphy *aphy;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ieee80211_hw *hw;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
@ -138,7 +140,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
|
||||
sc->sec_wiphy[i] = aphy;
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
|
||||
memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN);
|
||||
memcpy(addr, common->macaddr, ETH_ALEN);
|
||||
addr[0] |= 0x02; /* Locally managed address */
|
||||
/*
|
||||
* XOR virtual wiphy index into the least significant bits to generate
|
||||
|
@ -107,7 +107,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
|
||||
|
||||
ASSERT(tid->paused > 0);
|
||||
BUG_ON(tid->paused <= 0);
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
tid->paused--;
|
||||
@ -131,7 +131,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
struct list_head bf_head;
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
|
||||
ASSERT(tid->paused > 0);
|
||||
BUG_ON(tid->paused <= 0);
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
tid->paused--;
|
||||
@ -143,7 +143,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
|
||||
while (!list_empty(&tid->buf_q)) {
|
||||
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
|
||||
ASSERT(!bf_isretried(bf));
|
||||
BUG_ON(bf_isretried(bf));
|
||||
list_move_tail(&bf->list, &bf_head);
|
||||
ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
|
||||
}
|
||||
@ -178,7 +178,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
|
||||
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
|
||||
|
||||
ASSERT(tid->tx_buf[cindex] == NULL);
|
||||
BUG_ON(tid->tx_buf[cindex] != NULL);
|
||||
tid->tx_buf[cindex] = bf;
|
||||
|
||||
if (index >= ((tid->baw_tail - tid->baw_head) &
|
||||
@ -358,7 +358,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
else
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
} else {
|
||||
ASSERT(!list_empty(bf_q));
|
||||
BUG_ON(list_empty(bf_q));
|
||||
list_move_tail(&bf->list, &bf_head);
|
||||
}
|
||||
|
||||
@ -815,6 +815,7 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
|
||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_tx_queue_info qi;
|
||||
int qnum;
|
||||
|
||||
@ -854,9 +855,9 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
||||
return NULL;
|
||||
}
|
||||
if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"qnum %u out of range, max %u!\n",
|
||||
qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"qnum %u out of range, max %u!\n",
|
||||
qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
|
||||
ath9k_hw_releasetxqueue(ah, qnum);
|
||||
return NULL;
|
||||
}
|
||||
@ -884,9 +885,9 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
|
||||
switch (qtype) {
|
||||
case ATH9K_TX_QUEUE_DATA:
|
||||
if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"HAL AC %u out of range, max %zu!\n",
|
||||
haltype, ARRAY_SIZE(sc->tx.hwq_map));
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"HAL AC %u out of range, max %zu!\n",
|
||||
haltype, ARRAY_SIZE(sc->tx.hwq_map));
|
||||
return -1;
|
||||
}
|
||||
qnum = sc->tx.hwq_map[haltype];
|
||||
@ -914,9 +915,9 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
if (txq->axq_depth >= (ATH_TXBUF - 20)) {
|
||||
DPRINTF(sc, ATH_DBG_XMIT,
|
||||
"TX queue: %d is full, depth: %d\n",
|
||||
qnum, txq->axq_depth);
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
|
||||
"TX queue: %d is full, depth: %d\n",
|
||||
qnum, txq->axq_depth);
|
||||
ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
|
||||
txq->stopped = 1;
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
@ -945,7 +946,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
return 0;
|
||||
}
|
||||
|
||||
ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
|
||||
BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum);
|
||||
|
||||
ath9k_hw_get_txq_props(ah, qnum, &qi);
|
||||
qi.tqi_aifs = qinfo->tqi_aifs;
|
||||
@ -955,8 +956,8 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
qi.tqi_readyTime = qinfo->tqi_readyTime;
|
||||
|
||||
if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to update hardware queue %u!\n", qnum);
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"Unable to update hardware queue %u!\n", qnum);
|
||||
error = -EIO;
|
||||
} else {
|
||||
ath9k_hw_resettxqueue(ah, qnum);
|
||||
@ -1055,6 +1056,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
|
||||
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_txq *txq;
|
||||
int i, npend = 0;
|
||||
|
||||
@ -1076,14 +1078,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
|
||||
if (npend) {
|
||||
int r;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
"Unable to stop TxDMA. Reset HAL!\n");
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
|
||||
if (r)
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d\n",
|
||||
r);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d\n",
|
||||
r);
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
}
|
||||
|
||||
@ -1147,8 +1150,8 @@ int ath_tx_setup(struct ath_softc *sc, int haltype)
|
||||
struct ath_txq *txq;
|
||||
|
||||
if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"HAL AC %u out of range, max %zu!\n",
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"HAL AC %u out of range, max %zu!\n",
|
||||
haltype, ARRAY_SIZE(sc->tx.hwq_map));
|
||||
return 0;
|
||||
}
|
||||
@ -1172,6 +1175,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_buf *bf;
|
||||
|
||||
/*
|
||||
@ -1188,19 +1192,19 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
|
||||
txq->axq_depth++;
|
||||
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_QUEUE,
|
||||
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
|
||||
ath_print(common, ATH_DBG_QUEUE,
|
||||
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
|
||||
|
||||
if (txq->axq_link == NULL) {
|
||||
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
|
||||
DPRINTF(sc, ATH_DBG_XMIT,
|
||||
"TXDP[%u] = %llx (%p)\n",
|
||||
txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
"TXDP[%u] = %llx (%p)\n",
|
||||
txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
|
||||
} else {
|
||||
*txq->axq_link = bf->bf_daddr;
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
|
||||
txq->axq_qnum, txq->axq_link,
|
||||
ito64(bf->bf_daddr), bf->bf_desc);
|
||||
ath_print(common, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
|
||||
txq->axq_qnum, txq->axq_link,
|
||||
ito64(bf->bf_daddr), bf->bf_desc);
|
||||
}
|
||||
txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
|
||||
ath9k_hw_txstart(ah, txq->axq_qnum);
|
||||
@ -1452,6 +1456,7 @@ 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_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
const struct ath_rate_table *rt = sc->cur_rate_table;
|
||||
struct ath9k_11n_rate_series series[4];
|
||||
struct sk_buff *skb;
|
||||
@ -1507,7 +1512,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
|
||||
rix = rates[i].idx;
|
||||
series[i].Tries = rates[i].count;
|
||||
series[i].ChSel = sc->tx_chainmask;
|
||||
series[i].ChSel = common->tx_chainmask;
|
||||
|
||||
if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
|
||||
series[i].Rate = rt->info[rix].ratecode |
|
||||
@ -1587,7 +1592,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
|
||||
bf->bf_mpdu = NULL;
|
||||
kfree(tx_info_priv);
|
||||
tx_info->rate_driver_data[0] = NULL;
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n");
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on TX\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1669,12 +1675,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_buf *bf;
|
||||
int r;
|
||||
|
||||
bf = ath_tx_get_buffer(sc);
|
||||
if (!bf) {
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n");
|
||||
ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1682,7 +1689,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
if (unlikely(r)) {
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n");
|
||||
ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
|
||||
|
||||
/* upon ath_tx_processq() this TX queue will be resumed, we
|
||||
* guarantee this will happen by knowing beforehand that
|
||||
@ -1712,6 +1719,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
int hdrlen, padsize;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_control txctl;
|
||||
@ -1736,7 +1744,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
if (hdrlen & 3) {
|
||||
padsize = hdrlen % 4;
|
||||
if (skb_headroom(skb) < padsize) {
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
"TX CABQ padding failed\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
@ -1746,10 +1755,11 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
|
||||
txctl.txq = sc->beacon.cabq;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
"transmitting CABQ packet, skb: %p\n", skb);
|
||||
|
||||
if (ath_tx_start(hw, skb, &txctl) != 0) {
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
|
||||
ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -1768,10 +1778,11 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
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);
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
int hdrlen, padsize;
|
||||
int frame_type = ATH9K_NOT_INTERNAL;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
|
||||
ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
|
||||
|
||||
if (tx_info_priv) {
|
||||
hw = tx_info_priv->aphy->hw;
|
||||
@ -1805,8 +1816,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
|
||||
if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) {
|
||||
sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK;
|
||||
DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
|
||||
"received TX status (0x%x)\n",
|
||||
ath_print(common, ATH_DBG_PS,
|
||||
"Going back to sleep after having "
|
||||
"received TX status (0x%x)\n",
|
||||
sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
|
||||
SC_OP_WAIT_FOR_CAB |
|
||||
SC_OP_WAIT_FOR_PSPOLL_DATA |
|
||||
@ -1936,15 +1948,16 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
|
||||
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_buf *bf, *lastbf, *bf_held = NULL;
|
||||
struct list_head bf_head;
|
||||
struct ath_desc *ds;
|
||||
int txok;
|
||||
int status;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
|
||||
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
||||
txq->axq_link);
|
||||
ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
|
||||
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
||||
txq->axq_link);
|
||||
|
||||
for (;;) {
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
@ -2064,7 +2077,8 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (needreset) {
|
||||
DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n");
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
|
||||
"tx hung, resetting the chip\n");
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
|
||||
@ -2093,6 +2107,7 @@ void ath_tx_tasklet(struct ath_softc *sc)
|
||||
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
int error = 0;
|
||||
|
||||
spin_lock_init(&sc->tx.txbuflock);
|
||||
@ -2100,16 +2115,16 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
|
||||
"tx", nbufs, 1);
|
||||
if (error != 0) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Failed to allocate tx descriptors: %d\n", error);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Failed to allocate tx descriptors: %d\n", error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
|
||||
"beacon", ATH_BCBUF, 1);
|
||||
if (error != 0) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Failed to allocate beacon descriptors: %d\n", error);
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Failed to allocate beacon descriptors: %d\n", error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
32
drivers/net/wireless/ath/debug.c
Normal file
32
drivers/net/wireless/ath/debug.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ath.h"
|
||||
#include "debug.h"
|
||||
|
||||
void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (likely(!(common->debug_mask & dbg_mask)))
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
printk(KERN_DEBUG "ath: ");
|
||||
vprintk(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(ath_print);
|
77
drivers/net/wireless/ath/debug.h
Normal file
77
drivers/net/wireless/ath/debug.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATH_DEBUG_H
|
||||
#define ATH_DEBUG_H
|
||||
|
||||
#include "ath.h"
|
||||
|
||||
/**
|
||||
* enum ath_debug_level - atheros wireless debug level
|
||||
*
|
||||
* @ATH_DBG_RESET: reset processing
|
||||
* @ATH_DBG_QUEUE: hardware queue management
|
||||
* @ATH_DBG_EEPROM: eeprom processing
|
||||
* @ATH_DBG_CALIBRATE: periodic calibration
|
||||
* @ATH_DBG_INTERRUPT: interrupt processing
|
||||
* @ATH_DBG_REGULATORY: regulatory processing
|
||||
* @ATH_DBG_ANI: adaptive noise immunitive processing
|
||||
* @ATH_DBG_XMIT: basic xmit operation
|
||||
* @ATH_DBG_BEACON: beacon handling
|
||||
* @ATH_DBG_CONFIG: configuration of the hardware
|
||||
* @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT
|
||||
* @ATH_DBG_PS: power save processing
|
||||
* @ATH_DBG_HWTIMER: hardware timer handling
|
||||
* @ATH_DBG_BTCOEX: bluetooth coexistance
|
||||
* @ATH_DBG_ANY: enable all debugging
|
||||
*
|
||||
* The debug level is used to control the amount and type of debugging output
|
||||
* we want to see. Each driver has its own method for enabling debugging and
|
||||
* modifying debug level states -- but this is typically done through a
|
||||
* module parameter 'debug' along with a respective 'debug' debugfs file
|
||||
* entry.
|
||||
*/
|
||||
enum ATH_DEBUG {
|
||||
ATH_DBG_RESET = 0x00000001,
|
||||
ATH_DBG_QUEUE = 0x00000002,
|
||||
ATH_DBG_EEPROM = 0x00000004,
|
||||
ATH_DBG_CALIBRATE = 0x00000008,
|
||||
ATH_DBG_INTERRUPT = 0x00000010,
|
||||
ATH_DBG_REGULATORY = 0x00000020,
|
||||
ATH_DBG_ANI = 0x00000040,
|
||||
ATH_DBG_XMIT = 0x00000080,
|
||||
ATH_DBG_BEACON = 0x00000100,
|
||||
ATH_DBG_CONFIG = 0x00000200,
|
||||
ATH_DBG_FATAL = 0x00000400,
|
||||
ATH_DBG_PS = 0x00000800,
|
||||
ATH_DBG_HWTIMER = 0x00001000,
|
||||
ATH_DBG_BTCOEX = 0x00002000,
|
||||
ATH_DBG_ANY = 0xffffffff
|
||||
};
|
||||
|
||||
#define ATH_DBG_DEFAULT (ATH_DBG_FATAL)
|
||||
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...);
|
||||
#else
|
||||
static inline void ath_print(struct ath_common *common,
|
||||
int dbg_mask,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_ATH_DEBUG */
|
||||
|
||||
#endif /* ATH_DEBUG_H */
|
126
drivers/net/wireless/ath/hw.c
Normal file
126
drivers/net/wireless/ath/hw.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "ath.h"
|
||||
#include "reg.h"
|
||||
|
||||
#define REG_READ common->ops->read
|
||||
#define REG_WRITE common->ops->write
|
||||
|
||||
/**
|
||||
* ath_hw_set_bssid_mask - filter out bssids we listen
|
||||
*
|
||||
* @common: the ath_common struct for the device.
|
||||
*
|
||||
* BSSID masking is a method used by AR5212 and newer hardware to inform PCU
|
||||
* which bits of the interface's MAC address should be looked at when trying
|
||||
* to decide which packets to ACK. In station mode and AP mode with a single
|
||||
* BSS every bit matters since we lock to only one BSS. In AP mode with
|
||||
* multiple BSSes (virtual interfaces) not every bit matters because hw must
|
||||
* accept frames for all BSSes and so we tweak some bits of our mac address
|
||||
* in order to have multiple BSSes.
|
||||
*
|
||||
* NOTE: This is a simple filter and does *not* filter out all
|
||||
* relevant frames. Some frames that are not for us might get ACKed from us
|
||||
* by PCU because they just match the mask.
|
||||
*
|
||||
* When handling multiple BSSes you can get the BSSID mask by computing the
|
||||
* set of ~ ( MAC XOR BSSID ) for all bssids we handle.
|
||||
*
|
||||
* When you do this you are essentially computing the common bits of all your
|
||||
* BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
|
||||
* the MAC address to obtain the relevant bits and compare the result with
|
||||
* (frame's BSSID & mask) to see if they match.
|
||||
*
|
||||
* Simple example: on your card you have have two BSSes you have created with
|
||||
* BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
|
||||
* There is another BSSID-03 but you are not part of it. For simplicity's sake,
|
||||
* assuming only 4 bits for a mac address and for BSSIDs you can then have:
|
||||
*
|
||||
* \
|
||||
* MAC: 0001 |
|
||||
* BSSID-01: 0100 | --> Belongs to us
|
||||
* BSSID-02: 1001 |
|
||||
* /
|
||||
* -------------------
|
||||
* BSSID-03: 0110 | --> External
|
||||
* -------------------
|
||||
*
|
||||
* Our bssid_mask would then be:
|
||||
*
|
||||
* On loop iteration for BSSID-01:
|
||||
* ~(0001 ^ 0100) -> ~(0101)
|
||||
* -> 1010
|
||||
* bssid_mask = 1010
|
||||
*
|
||||
* On loop iteration for BSSID-02:
|
||||
* bssid_mask &= ~(0001 ^ 1001)
|
||||
* bssid_mask = (1010) & ~(0001 ^ 1001)
|
||||
* bssid_mask = (1010) & ~(1001)
|
||||
* bssid_mask = (1010) & (0110)
|
||||
* bssid_mask = 0010
|
||||
*
|
||||
* A bssid_mask of 0010 means "only pay attention to the second least
|
||||
* significant bit". This is because its the only bit common
|
||||
* amongst the MAC and all BSSIDs we support. To findout what the real
|
||||
* common bit is we can simply "&" the bssid_mask now with any BSSID we have
|
||||
* or our MAC address (we assume the hardware uses the MAC address).
|
||||
*
|
||||
* Now, suppose there's an incoming frame for BSSID-03:
|
||||
*
|
||||
* IFRAME-01: 0110
|
||||
*
|
||||
* An easy eye-inspeciton of this already should tell you that this frame
|
||||
* will not pass our check. This is beacuse the bssid_mask tells the
|
||||
* hardware to only look at the second least significant bit and the
|
||||
* common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
|
||||
* as 1, which does not match 0.
|
||||
*
|
||||
* So with IFRAME-01 we *assume* the hardware will do:
|
||||
*
|
||||
* allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
||||
* --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
|
||||
* --> allow = (0010) == 0000 ? 1 : 0;
|
||||
* --> allow = 0
|
||||
*
|
||||
* Lets now test a frame that should work:
|
||||
*
|
||||
* IFRAME-02: 0001 (we should allow)
|
||||
*
|
||||
* allow = (0001 & 1010) == 1010
|
||||
*
|
||||
* allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
||||
* --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
|
||||
* --> allow = (0010) == (0010)
|
||||
* --> allow = 1
|
||||
*
|
||||
* Other examples:
|
||||
*
|
||||
* IFRAME-03: 0100 --> allowed
|
||||
* IFRAME-04: 1001 --> allowed
|
||||
* IFRAME-05: 1101 --> allowed but its not for us!!!
|
||||
*
|
||||
*/
|
||||
void ath_hw_setbssidmask(struct ath_common *common)
|
||||
{
|
||||
void *ah = common->ah;
|
||||
|
||||
REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
|
||||
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
|
||||
}
|
||||
EXPORT_SYMBOL(ath_hw_setbssidmask);
|
27
drivers/net/wireless/ath/reg.h
Normal file
27
drivers/net/wireless/ath/reg.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATH_REGISTERS_H
|
||||
#define ATH_REGISTERS_H
|
||||
|
||||
/*
|
||||
* BSSID mask registers. See ath_hw_set_bssid_mask()
|
||||
* for detailed documentation about these registers.
|
||||
*/
|
||||
#define AR_BSSMSKL 0x80e0
|
||||
#define AR_BSSMSKU 0x80e4
|
||||
|
||||
#endif /* ATH_REGISTERS_H */
|
@ -379,6 +379,8 @@ static void lpphy_save_dig_flt_state(struct b43_wldev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* lpphy_restore_dig_flt_state is unused but kept as a reference */
|
||||
#if 0
|
||||
static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
|
||||
{
|
||||
static const u16 addr[] = {
|
||||
@ -399,6 +401,7 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
|
||||
for (i = 0; i < ARRAY_SIZE(addr); i++)
|
||||
b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
|
||||
{
|
||||
@ -887,6 +890,8 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
|
||||
}
|
||||
}
|
||||
|
||||
/* lpphy_disable_rx_gain_override is unused but kept as a reference */
|
||||
#if 0
|
||||
static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
|
||||
{
|
||||
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
|
||||
@ -902,6 +907,7 @@ static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
|
||||
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
|
||||
{
|
||||
|
@ -2,6 +2,8 @@ config HOSTAP
|
||||
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
|
||||
depends on WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select CRYPTO
|
||||
select CRYPTO_ARC4
|
||||
select CRYPTO_ECB
|
||||
|
@ -6,6 +6,8 @@ config IPW2100
|
||||
tristate "Intel PRO/Wireless 2100 Network Connection"
|
||||
depends on PCI && WLAN_80211 && CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select LIB80211
|
||||
select LIBIPW
|
||||
@ -63,8 +65,10 @@ config IPW2100_DEBUG
|
||||
|
||||
config IPW2200
|
||||
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
|
||||
depends on PCI && WLAN_80211 && CFG80211
|
||||
depends on PCI && WLAN_80211 && CFG80211 && CFG80211_WEXT
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select LIB80211
|
||||
select LIBIPW
|
||||
@ -152,6 +156,7 @@ config LIBIPW
|
||||
tristate
|
||||
depends on PCI && WLAN_80211 && CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select CRYPTO
|
||||
select CRYPTO_ARC4
|
||||
select CRYPTO_ECB
|
||||
|
@ -11275,6 +11275,7 @@ static int ipw_up(struct ipw_priv *priv)
|
||||
if (!(priv->config & CFG_CUSTOM_MAC))
|
||||
eeprom_parse_mac(priv, priv->mac_addr);
|
||||
memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
|
||||
memcpy(priv->net_dev->perm_addr, priv->mac_addr, ETH_ALEN);
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) {
|
||||
if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE],
|
||||
|
@ -1,17 +1,7 @@
|
||||
config IWLWIFI
|
||||
tristate "Intel Wireless Wifi"
|
||||
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
|
||||
select LIB80211
|
||||
select FW_LOADER
|
||||
select MAC80211_LEDS if IWLWIFI_LEDS
|
||||
select LEDS_CLASS if IWLWIFI_LEDS
|
||||
|
||||
config IWLWIFI_LEDS
|
||||
bool "Enable LED support in iwlagn and iwl3945 drivers"
|
||||
depends on IWLWIFI
|
||||
default y
|
||||
---help---
|
||||
Select this if you want LED support.
|
||||
|
||||
config IWLWIFI_SPECTRUM_MEASUREMENT
|
||||
bool "Enable Spectrum Measurement in iwlagn driver"
|
||||
@ -50,6 +40,24 @@ config IWLWIFI_DEBUGFS
|
||||
---help---
|
||||
Enable creation of debugfs files for the iwlwifi drivers.
|
||||
|
||||
config IWLWIFI_DEVICE_TRACING
|
||||
bool "iwlwifi device access tracing"
|
||||
depends on IWLWIFI
|
||||
depends on EVENT_TRACING
|
||||
help
|
||||
Say Y here to trace all commands, including TX frames and IO
|
||||
accesses, sent to the device. If you say yes, iwlwifi will
|
||||
register with the ftrace framework for event tracing and dump
|
||||
all this information to the ringbuffer, you may need to
|
||||
increase the ringbuffer size. See the ftrace documentation
|
||||
for more information.
|
||||
|
||||
When tracing is not enabled, this option still has some
|
||||
(though rather small) overhead.
|
||||
|
||||
If unsure, say Y so we can help you better when problems
|
||||
occur.
|
||||
|
||||
config IWLAGN
|
||||
tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
|
||||
depends on IWLWIFI
|
||||
|
@ -1,20 +1,22 @@
|
||||
obj-$(CONFIG_IWLWIFI) += iwlcore.o
|
||||
iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
|
||||
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
|
||||
iwlcore-objs += iwl-scan.o
|
||||
iwlcore-objs += iwl-scan.o iwl-led.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
|
||||
CFLAGS_iwl-devtrace.o := -I$(src)
|
||||
|
||||
# AGN
|
||||
obj-$(CONFIG_IWLAGN) += iwlagn.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
|
||||
|
||||
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
|
||||
|
||||
# 3945
|
||||
obj-$(CONFIG_IWL3945) += iwl3945.o
|
||||
iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-agn-led.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL1000_UCODE_API_MAX 3
|
||||
@ -76,7 +77,10 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
|
||||
/* NIC configuration for 1000 series */
|
||||
static void iwl1000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl5000_nic_config(priv);
|
||||
/* set CSR_HW_CONFIG_REG for uCode use */
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
|
||||
/* Setting digital SVR for 1000 card to 1.32V */
|
||||
/* locking is acquired in iwl_set_bits_mask_prph() function */
|
||||
@ -108,7 +112,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.stop = iwl5000_apm_stop,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl1000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
@ -142,6 +146,7 @@ static struct iwl_ops iwl1000_ops = {
|
||||
.lib = &iwl1000_lib,
|
||||
.hcmd = &iwl5000_hcmd,
|
||||
.utils = &iwl5000_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
@ -152,7 +157,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
.sku = IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl1000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
@ -161,5 +166,29 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1000_bg_cfg = {
|
||||
.name = "1000 Series BG",
|
||||
.fw_name_pre = IWL1000_FW_PRE,
|
||||
.ucode_api_max = IWL1000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL1000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl1000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
|
||||
|
@ -24,8 +24,6 @@
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@ -43,388 +41,51 @@
|
||||
#include "iwl-3945.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-3945-led.h"
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static const char *led_type_str[] = {
|
||||
__stringify(IWL_LED_TRG_TX),
|
||||
__stringify(IWL_LED_TRG_RX),
|
||||
__stringify(IWL_LED_TRG_ASSOC),
|
||||
__stringify(IWL_LED_TRG_RADIO),
|
||||
NULL
|
||||
};
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
static const struct {
|
||||
u16 brightness;
|
||||
u8 on_time;
|
||||
u8 off_time;
|
||||
} blink_tbl[] =
|
||||
{
|
||||
{300, 25, 25},
|
||||
{200, 40, 40},
|
||||
{100, 55, 55},
|
||||
{70, 65, 65},
|
||||
{50, 75, 75},
|
||||
{20, 85, 85},
|
||||
{15, 95, 95 },
|
||||
{10, 110, 110},
|
||||
{5, 130, 130},
|
||||
{0, 167, 167},
|
||||
/* SOLID_ON */
|
||||
{-1, IWL_LED_SOLID, 0}
|
||||
};
|
||||
|
||||
#define IWL_1MB_RATE (128 * 1024)
|
||||
#define IWL_LED_THRESHOLD (16)
|
||||
#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
|
||||
#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
|
||||
|
||||
static void iwl3945_led_cmd_callback(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
|
||||
{
|
||||
return fls(0x000000FF & (u32)brightness);
|
||||
}
|
||||
|
||||
/* Send led command */
|
||||
static int iwl_send_led_cmd(struct iwl_priv *priv,
|
||||
struct iwl_led_cmd *led_cmd)
|
||||
static int iwl3945_send_led_cmd(struct iwl_priv *priv,
|
||||
struct iwl_led_cmd *led_cmd)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_LEDS_CMD,
|
||||
.len = sizeof(struct iwl_led_cmd),
|
||||
.data = led_cmd,
|
||||
.flags = CMD_ASYNC,
|
||||
.callback = iwl3945_led_cmd_callback,
|
||||
.callback = NULL,
|
||||
};
|
||||
|
||||
return iwl_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set led on command */
|
||||
static int iwl3945_led_pattern(struct iwl_priv *priv, int led_id,
|
||||
unsigned int idx)
|
||||
static int iwl3945_led_on(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_led_cmd led_cmd = {
|
||||
.id = led_id,
|
||||
.interval = IWL_DEF_LED_INTRVL
|
||||
};
|
||||
|
||||
BUG_ON(idx > IWL_MAX_BLINK_TBL);
|
||||
|
||||
led_cmd.on = blink_tbl[idx].on_time;
|
||||
led_cmd.off = blink_tbl[idx].off_time;
|
||||
|
||||
return iwl_send_led_cmd(priv, &led_cmd);
|
||||
}
|
||||
|
||||
|
||||
/* Set led on command */
|
||||
static int iwl3945_led_on(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
struct iwl_led_cmd led_cmd = {
|
||||
.id = led_id,
|
||||
.id = IWL_LED_LINK,
|
||||
.on = IWL_LED_SOLID,
|
||||
.off = 0,
|
||||
.interval = IWL_DEF_LED_INTRVL
|
||||
};
|
||||
return iwl_send_led_cmd(priv, &led_cmd);
|
||||
return iwl3945_send_led_cmd(priv, &led_cmd);
|
||||
}
|
||||
|
||||
/* Set led off command */
|
||||
static int iwl3945_led_off(struct iwl_priv *priv, int led_id)
|
||||
static int iwl3945_led_off(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_led_cmd led_cmd = {
|
||||
.id = led_id,
|
||||
.id = IWL_LED_LINK,
|
||||
.on = 0,
|
||||
.off = 0,
|
||||
.interval = IWL_DEF_LED_INTRVL
|
||||
};
|
||||
IWL_DEBUG_LED(priv, "led off %d\n", led_id);
|
||||
return iwl_send_led_cmd(priv, &led_cmd);
|
||||
IWL_DEBUG_LED(priv, "led off\n");
|
||||
return iwl3945_send_led_cmd(priv, &led_cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set led on in case of association
|
||||
* */
|
||||
static int iwl3945_led_associate(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "Associated\n");
|
||||
|
||||
priv->allow_blinking = 1;
|
||||
return iwl3945_led_on(priv, led_id);
|
||||
}
|
||||
/* Set Led off in case of disassociation */
|
||||
static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "Disassociated\n");
|
||||
|
||||
priv->allow_blinking = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* brightness call back function for Tx/Rx LED
|
||||
*/
|
||||
static int iwl3945_led_associated(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
|
||||
!test_bit(STATUS_READY, &priv->status))
|
||||
return 0;
|
||||
|
||||
|
||||
/* start counting Tx/Rx bytes */
|
||||
if (!priv->last_blink_time && priv->allow_blinking)
|
||||
priv->last_blink_time = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* brightness call back for association and radio
|
||||
*/
|
||||
static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct iwl_led *led = container_of(led_cdev,
|
||||
struct iwl_led, led_dev);
|
||||
struct iwl_priv *priv = led->priv;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n",
|
||||
led_type_str[led->type], brightness);
|
||||
|
||||
switch (brightness) {
|
||||
case LED_FULL:
|
||||
if (led->led_on)
|
||||
led->led_on(priv, IWL_LED_LINK);
|
||||
break;
|
||||
case LED_OFF:
|
||||
if (led->led_off)
|
||||
led->led_off(priv, IWL_LED_LINK);
|
||||
break;
|
||||
default:
|
||||
if (led->led_pattern) {
|
||||
int idx = iwl3945_brightness_to_idx(brightness);
|
||||
led->led_pattern(priv, IWL_LED_LINK, idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register led class with the system
|
||||
*/
|
||||
static int iwl3945_led_register_led(struct iwl_priv *priv,
|
||||
struct iwl_led *led,
|
||||
enum led_type type, u8 set_led,
|
||||
char *trigger)
|
||||
{
|
||||
struct device *device = wiphy_dev(priv->hw->wiphy);
|
||||
int ret;
|
||||
|
||||
led->led_dev.name = led->name;
|
||||
led->led_dev.brightness_set = iwl3945_led_brightness_set;
|
||||
led->led_dev.default_trigger = trigger;
|
||||
|
||||
led->priv = priv;
|
||||
led->type = type;
|
||||
|
||||
ret = led_classdev_register(device, &led->led_dev);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error: failed to register led handler.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
led->registered = 1;
|
||||
|
||||
if (set_led && led->led_on)
|
||||
led->led_on(priv, IWL_LED_LINK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* calculate blink rate according to last 2 sec Tx/Rx activities
|
||||
*/
|
||||
static inline u8 get_blink_rate(struct iwl_priv *priv)
|
||||
{
|
||||
int index;
|
||||
s64 tpt = priv->rxtxpackets;
|
||||
|
||||
if (tpt < 0)
|
||||
tpt = -tpt;
|
||||
|
||||
IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt);
|
||||
|
||||
if (!priv->allow_blinking)
|
||||
index = IWL_MAX_BLINK_TBL;
|
||||
else
|
||||
for (index = 0; index < IWL_MAX_BLINK_TBL; index++)
|
||||
if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE))
|
||||
break;
|
||||
|
||||
IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function called from handler. Since setting Led command can
|
||||
* happen very frequent we postpone led command to be called from
|
||||
* REPLY handler so we know ucode is up
|
||||
*/
|
||||
void iwl3945_led_background(struct iwl_priv *priv)
|
||||
{
|
||||
u8 blink_idx;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||
priv->last_blink_time = 0;
|
||||
return;
|
||||
}
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
priv->last_blink_time = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->allow_blinking) {
|
||||
priv->last_blink_time = 0;
|
||||
if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
|
||||
priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
|
||||
iwl3945_led_pattern(priv, IWL_LED_LINK,
|
||||
IWL_SOLID_BLINK_IDX);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!priv->last_blink_time ||
|
||||
!time_after(jiffies, priv->last_blink_time +
|
||||
msecs_to_jiffies(1000)))
|
||||
return;
|
||||
|
||||
blink_idx = get_blink_rate(priv);
|
||||
|
||||
/* call only if blink rate change */
|
||||
if (blink_idx != priv->last_blink_rate)
|
||||
iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx);
|
||||
|
||||
priv->last_blink_time = jiffies;
|
||||
priv->last_blink_rate = blink_idx;
|
||||
priv->rxtxpackets = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Register all led handler */
|
||||
int iwl3945_led_register(struct iwl_priv *priv)
|
||||
{
|
||||
char *trigger;
|
||||
int ret;
|
||||
|
||||
priv->last_blink_rate = 0;
|
||||
priv->rxtxpackets = 0;
|
||||
priv->led_tpt = 0;
|
||||
priv->last_blink_time = 0;
|
||||
priv->allow_blinking = 0;
|
||||
|
||||
trigger = ieee80211_get_radio_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_RADIO].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on;
|
||||
priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off;
|
||||
priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
|
||||
|
||||
ret = iwl3945_led_register_led(priv,
|
||||
&priv->led[IWL_LED_TRG_RADIO],
|
||||
IWL_LED_TRG_RADIO, 1, trigger);
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
trigger = ieee80211_get_assoc_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_ASSOC].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
ret = iwl3945_led_register_led(priv,
|
||||
&priv->led[IWL_LED_TRG_ASSOC],
|
||||
IWL_LED_TRG_ASSOC, 0, trigger);
|
||||
|
||||
/* for assoc always turn led on */
|
||||
priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate;
|
||||
priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate;
|
||||
priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
trigger = ieee80211_get_rx_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_RX].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
ret = iwl3945_led_register_led(priv,
|
||||
&priv->led[IWL_LED_TRG_RX],
|
||||
IWL_LED_TRG_RX, 0, trigger);
|
||||
|
||||
priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
|
||||
priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
|
||||
priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern;
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
trigger = ieee80211_get_tx_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_TX].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
ret = iwl3945_led_register_led(priv,
|
||||
&priv->led[IWL_LED_TRG_TX],
|
||||
IWL_LED_TRG_TX, 0, trigger);
|
||||
|
||||
priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
|
||||
priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
|
||||
priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_fail:
|
||||
iwl3945_led_unregister(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* unregister led class */
|
||||
static void iwl3945_led_unregister_led(struct iwl_led *led, u8 set_led)
|
||||
{
|
||||
if (!led->registered)
|
||||
return;
|
||||
|
||||
led_classdev_unregister(&led->led_dev);
|
||||
|
||||
if (set_led)
|
||||
led->led_dev.brightness_set(&led->led_dev, LED_OFF);
|
||||
led->registered = 0;
|
||||
}
|
||||
|
||||
/* Unregister all led handlers */
|
||||
void iwl3945_led_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
|
||||
iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
|
||||
iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
|
||||
iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
const struct iwl_led_ops iwl3945_led_ops = {
|
||||
.cmd = iwl3945_send_led_cmd,
|
||||
.on = iwl3945_led_on,
|
||||
.off = iwl3945_led_off,
|
||||
};
|
||||
|
@ -24,23 +24,9 @@
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef IWL3945_LEDS_H
|
||||
#define IWL3945_LEDS_H
|
||||
#ifndef __iwl_3945_led_h__
|
||||
#define __iwl_3945_led_h__
|
||||
|
||||
struct iwl_priv;
|
||||
extern const struct iwl_led_ops iwl3945_led_ops;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
|
||||
#include "iwl-led.h"
|
||||
|
||||
extern int iwl3945_led_register(struct iwl_priv *priv);
|
||||
extern void iwl3945_led_unregister(struct iwl_priv *priv);
|
||||
extern void iwl3945_led_background(struct iwl_priv *priv);
|
||||
|
||||
#else
|
||||
static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; }
|
||||
static inline void iwl3945_led_unregister(struct iwl_priv *priv) {}
|
||||
static inline void iwl3945_led_background(struct iwl_priv *priv) {}
|
||||
|
||||
#endif /* IWLWIFI_LEDS*/
|
||||
#endif /* IWL3945_LEDS_H */
|
||||
#endif /* __iwl_3945_led_h__ */
|
||||
|
@ -46,7 +46,8 @@
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-agn-rs.h"
|
||||
#include "iwl-led.h"
|
||||
#include "iwl-3945-led.h"
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \
|
||||
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
|
||||
@ -359,7 +360,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
||||
|
||||
memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
|
||||
|
||||
iwl3945_led_background(priv);
|
||||
iwl_leds_background(priv);
|
||||
|
||||
priv->last_statistics_time = jiffies;
|
||||
}
|
||||
@ -572,10 +573,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
(struct ieee80211_hdr *)rxb->skb->data,
|
||||
le32_to_cpu(rx_end->status), stats);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
if (ieee80211_is_data(hdr->frame_control))
|
||||
priv->rxtxpackets += len;
|
||||
#endif
|
||||
iwl_update_stats(priv, false, hdr->frame_control, len);
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
|
||||
@ -1002,8 +999,9 @@ static int iwl3945_apm_init(struct iwl_priv *priv)
|
||||
* D0U* --> D0A* state */
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
goto out;
|
||||
@ -1170,48 +1168,9 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
|
||||
iwl3945_hw_txq_ctx_free(priv);
|
||||
}
|
||||
|
||||
static int iwl3945_apm_stop_master(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* set stop master bit */
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
|
||||
|
||||
iwl_poll_direct_bit(priv, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
IWL_DEBUG_INFO(priv, "stop master\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl3945_apm_stop(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
iwl3945_apm_stop_master(priv);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
udelay(10);
|
||||
/* clear "init complete" move adapter D0A* --> D0U state */
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int iwl3945_apm_reset(struct iwl_priv *priv)
|
||||
{
|
||||
iwl3945_apm_stop_master(priv);
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
@ -1219,8 +1178,9 @@ static int iwl3945_apm_reset(struct iwl_priv *priv)
|
||||
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
|
||||
iwl_write_prph(priv, APMG_CLK_CTRL_REG,
|
||||
APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
@ -2844,7 +2804,7 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
.apm_ops = {
|
||||
.init = iwl3945_apm_init,
|
||||
.reset = iwl3945_apm_reset,
|
||||
.stop = iwl3945_apm_stop,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl3945_nic_config,
|
||||
.set_pwr_src = iwl3945_set_pwr_src,
|
||||
},
|
||||
@ -2880,6 +2840,7 @@ static struct iwl_ops iwl3945_ops = {
|
||||
.lib = &iwl3945_lib,
|
||||
.hcmd = &iwl3945_hcmd,
|
||||
.utils = &iwl3945_hcmd_utils,
|
||||
.led = &iwl3945_led_ops,
|
||||
};
|
||||
|
||||
static struct iwl_cfg iwl3945_bg_cfg = {
|
||||
@ -2894,6 +2855,7 @@ static struct iwl_cfg iwl3945_bg_cfg = {
|
||||
.mod_params = &iwl3945_mod_params,
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
.led_compensation = 64,
|
||||
};
|
||||
|
||||
static struct iwl_cfg iwl3945_abg_cfg = {
|
||||
@ -2908,6 +2870,7 @@ static struct iwl_cfg iwl3945_abg_cfg = {
|
||||
.mod_params = &iwl3945_mod_params,
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
.led_compensation = 64,
|
||||
};
|
||||
|
||||
struct pci_device_id iwl3945_hw_card_ids[] = {
|
||||
|
@ -46,7 +46,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-power.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-3945-led.h"
|
||||
#include "iwl-led.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL3945_UCODE_API_MAX 2
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-agn-led.h"
|
||||
|
||||
static int iwl4965_send_tx_power(struct iwl_priv *priv);
|
||||
static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
|
||||
@ -334,7 +335,8 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock stabilization */
|
||||
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
@ -395,45 +397,11 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int iwl4965_apm_stop_master(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* set stop master bit */
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
|
||||
|
||||
iwl_poll_direct_bit(priv, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
IWL_DEBUG_INFO(priv, "stop master\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl4965_apm_stop(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
iwl4965_apm_stop_master(priv);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
udelay(10);
|
||||
/* clear "init complete" move adapter D0A* --> D0U state */
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int iwl4965_apm_reset(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
iwl4965_apm_stop_master(priv);
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
@ -444,7 +412,8 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
|
||||
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@ -495,14 +464,15 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
|
||||
static void iwl4965_gain_computation(struct iwl_priv *priv,
|
||||
u32 *average_noise,
|
||||
u16 min_average_noise_antenna_i,
|
||||
u32 min_average_noise)
|
||||
u32 min_average_noise,
|
||||
u8 default_chain)
|
||||
{
|
||||
int i, ret;
|
||||
struct iwl_chain_noise_data *data = &priv->chain_noise_data;
|
||||
|
||||
data->delta_gain_code[min_average_noise_antenna_i] = 0;
|
||||
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
for (i = default_chain; i < NUM_RX_CHAINS; i++) {
|
||||
s32 delta_g = 0;
|
||||
|
||||
if (!(data->disconn_array[i]) &&
|
||||
@ -662,7 +632,8 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
||||
iwl_write_targ_mem(priv, a, 0);
|
||||
for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
|
||||
iwl_write_targ_mem(priv, a, 0);
|
||||
for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
|
||||
for (; a < priv->scd_base_addr +
|
||||
IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
|
||||
iwl_write_targ_mem(priv, a, 0);
|
||||
|
||||
/* Tel 4965 where to find Tx byte count tables */
|
||||
@ -2303,7 +2274,7 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
.apm_ops = {
|
||||
.init = iwl4965_apm_init,
|
||||
.reset = iwl4965_apm_reset,
|
||||
.stop = iwl4965_apm_stop,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl4965_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
@ -2339,6 +2310,7 @@ static struct iwl_ops iwl4965_ops = {
|
||||
.lib = &iwl4965_lib,
|
||||
.hcmd = &iwl4965_hcmd,
|
||||
.utils = &iwl4965_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl4965_agn_cfg = {
|
||||
@ -2355,26 +2327,29 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
.broken_powersave = true,
|
||||
.led_compensation = 61,
|
||||
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
/* Module firmware */
|
||||
MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
|
||||
|
||||
module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
|
||||
module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
|
||||
module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
|
||||
module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
|
||||
module_param_named(
|
||||
disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444);
|
||||
disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
|
||||
|
||||
module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
|
||||
module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(queues_num, "number of hw queues.");
|
||||
/* 11n */
|
||||
module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444);
|
||||
module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
|
||||
module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444);
|
||||
module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K,
|
||||
int, S_IRUGO);
|
||||
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
|
||||
|
||||
module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444);
|
||||
module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error");
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-agn-led.h"
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-6000-hw.h"
|
||||
|
||||
@ -71,26 +72,6 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_HCCA_2
|
||||
};
|
||||
|
||||
/* FIXME: same implementation as 4965 */
|
||||
static int iwl5000_apm_stop_master(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* set stop master bit */
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
|
||||
|
||||
iwl_poll_direct_bit(priv, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
IWL_DEBUG_INFO(priv, "stop master\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int iwl5000_apm_init(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -117,7 +98,8 @@ int iwl5000_apm_init(struct iwl_priv *priv)
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock stabilization */
|
||||
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
@ -136,31 +118,11 @@ int iwl5000_apm_init(struct iwl_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: this is identical to 4965 */
|
||||
void iwl5000_apm_stop(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
iwl5000_apm_stop_master(priv);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
udelay(10);
|
||||
|
||||
/* clear "init complete" move adapter D0A* --> D0U state */
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
|
||||
int iwl5000_apm_reset(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
iwl5000_apm_stop_master(priv);
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
@ -177,7 +139,8 @@ int iwl5000_apm_reset(struct iwl_priv *priv)
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock stabilization */
|
||||
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
@ -198,7 +161,7 @@ out:
|
||||
}
|
||||
|
||||
|
||||
/* NIC configuration for 5000 series and up */
|
||||
/* NIC configuration for 5000 series */
|
||||
void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -221,7 +184,7 @@ void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
|
||||
|
||||
/* write radio config values to register */
|
||||
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_5000_RF_CFG_TYPE_MAX)
|
||||
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX)
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
|
||||
EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
|
||||
@ -301,14 +264,17 @@ u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
|
||||
static void iwl5000_gain_computation(struct iwl_priv *priv,
|
||||
u32 average_noise[NUM_RX_CHAINS],
|
||||
u16 min_average_noise_antenna_i,
|
||||
u32 min_average_noise)
|
||||
u32 min_average_noise,
|
||||
u8 default_chain)
|
||||
{
|
||||
int i;
|
||||
s32 delta_g;
|
||||
struct iwl_chain_noise_data *data = &priv->chain_noise_data;
|
||||
|
||||
/* Find Gain Code for the antennas B and C */
|
||||
for (i = 1; i < NUM_RX_CHAINS; i++) {
|
||||
/*
|
||||
* Find Gain Code for the chains based on "default chain"
|
||||
*/
|
||||
for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) {
|
||||
if ((data->disconn_array[i])) {
|
||||
data->delta_gain_code[i] = 0;
|
||||
continue;
|
||||
@ -745,7 +711,8 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
|
||||
for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET;
|
||||
a += 4)
|
||||
iwl_write_targ_mem(priv, a, 0);
|
||||
for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
|
||||
for (; a < priv->scd_base_addr +
|
||||
IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
|
||||
iwl_write_targ_mem(priv, a, 0);
|
||||
|
||||
iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
|
||||
@ -833,16 +800,8 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
|
||||
|
||||
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
|
||||
case CSR_HW_REV_TYPE_6x00:
|
||||
case CSR_HW_REV_TYPE_6x50:
|
||||
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
|
||||
break;
|
||||
default:
|
||||
priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE;
|
||||
}
|
||||
priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE;
|
||||
|
||||
priv->hw_params.max_bsm_size = 0;
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
@ -1458,6 +1417,24 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
|
||||
return max_rssi - agc - IWL49_RSSI_OFFSET;
|
||||
}
|
||||
|
||||
static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
||||
{
|
||||
struct iwl_tx_ant_config_cmd tx_ant_cmd = {
|
||||
.valid = cpu_to_le32(valid_tx_ant),
|
||||
};
|
||||
|
||||
if (IWL_UCODE_API(priv->ucode_ver) > 1) {
|
||||
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
|
||||
return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD,
|
||||
sizeof(struct iwl_tx_ant_config_cmd),
|
||||
&tx_ant_cmd);
|
||||
} else {
|
||||
IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define IWL5000_UCODE_GET(item) \
|
||||
static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\
|
||||
u32 api_ver) \
|
||||
@ -1500,6 +1477,7 @@ struct iwl_hcmd_ops iwl5000_hcmd = {
|
||||
.rxon_assoc = iwl5000_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.set_tx_ant = iwl5000_send_tx_ant_config,
|
||||
};
|
||||
|
||||
struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
|
||||
@ -1545,7 +1523,7 @@ struct iwl_lib_ops iwl5000_lib = {
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.stop = iwl5000_apm_stop,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
@ -1597,7 +1575,7 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.stop = iwl5000_apm_stop,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
@ -1626,11 +1604,12 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
},
|
||||
};
|
||||
|
||||
struct iwl_ops iwl5000_ops = {
|
||||
static struct iwl_ops iwl5000_ops = {
|
||||
.ucode = &iwl5000_ucode,
|
||||
.lib = &iwl5000_lib,
|
||||
.hcmd = &iwl5000_hcmd,
|
||||
.utils = &iwl5000_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
static struct iwl_ops iwl5150_ops = {
|
||||
@ -1638,6 +1617,7 @@ static struct iwl_ops iwl5150_ops = {
|
||||
.lib = &iwl5150_lib,
|
||||
.hcmd = &iwl5000_hcmd,
|
||||
.utils = &iwl5000_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
struct iwl_mod_params iwl50_mod_params = {
|
||||
@ -1664,6 +1644,8 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_bg_cfg = {
|
||||
@ -1681,6 +1663,8 @@ struct iwl_cfg iwl5100_bg_cfg = {
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_abg_cfg = {
|
||||
@ -1698,6 +1682,8 @@ struct iwl_cfg iwl5100_abg_cfg = {
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_agn_cfg = {
|
||||
@ -1715,6 +1701,8 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5350_agn_cfg = {
|
||||
@ -1732,6 +1720,8 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5150_agn_cfg = {
|
||||
@ -1749,19 +1739,22 @@ struct iwl_cfg iwl5150_agn_cfg = {
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
|
||||
|
||||
module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444);
|
||||
module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(swcrypto50,
|
||||
"using software crypto engine (default 0 [hardware])\n");
|
||||
module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444);
|
||||
module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series");
|
||||
module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444);
|
||||
module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality");
|
||||
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444);
|
||||
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K,
|
||||
int, S_IRUGO);
|
||||
MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series");
|
||||
module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444);
|
||||
module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error");
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-6000-hw.h"
|
||||
#include "iwl-agn-led.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL6000_UCODE_API_MAX 4
|
||||
@ -71,7 +73,21 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||
/* NIC configuration for 6000 series */
|
||||
static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl5000_nic_config(priv);
|
||||
u16 radio_cfg;
|
||||
|
||||
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
|
||||
|
||||
/* write radio config values to register */
|
||||
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
|
||||
EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
|
||||
EEPROM_RF_CFG_DASH_MSK(radio_cfg));
|
||||
|
||||
/* set CSR_HW_CONFIG_REG for uCode use */
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
|
||||
/* no locking required for register write */
|
||||
if (priv->cfg->pa_type == IWL_PA_HYBRID) {
|
||||
@ -86,8 +102,76 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
/* else do nothing, uCode configured */
|
||||
}
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||
.min_nrg_cck = 97,
|
||||
.max_nrg_cck = 0, /* not used, set to 0 */
|
||||
.auto_corr_min_ofdm = 80,
|
||||
.auto_corr_min_ofdm_mrc = 128,
|
||||
.auto_corr_min_ofdm_x1 = 105,
|
||||
.auto_corr_min_ofdm_mrc_x1 = 192,
|
||||
|
||||
.auto_corr_max_ofdm = 145,
|
||||
.auto_corr_max_ofdm_mrc = 232,
|
||||
.auto_corr_max_ofdm_x1 = 145,
|
||||
.auto_corr_max_ofdm_mrc_x1 = 232,
|
||||
|
||||
.auto_corr_min_cck = 125,
|
||||
.auto_corr_max_cck = 175,
|
||||
.auto_corr_min_cck_mrc = 160,
|
||||
.auto_corr_max_cck_mrc = 310,
|
||||
.nrg_th_cck = 97,
|
||||
.nrg_th_ofdm = 100,
|
||||
};
|
||||
|
||||
static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
|
||||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
|
||||
IWL_ERR(priv,
|
||||
"invalid queues_num, should be between %d and %d\n",
|
||||
IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
|
||||
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
|
||||
priv->hw_params.scd_bc_tbls_size =
|
||||
IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
|
||||
|
||||
priv->hw_params.max_bsm_size = 0;
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
|
||||
|
||||
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
||||
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
priv->hw_params.sens = &iwl6000_sensitivity;
|
||||
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_BASE_BAND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iwl_lib_ops iwl6000_lib = {
|
||||
.set_hw_params = iwl5000_hw_set_hw_params,
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
|
||||
.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
|
||||
.txq_set_sched = iwl5000_txq_set_sched,
|
||||
@ -109,7 +193,7 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.stop = iwl5000_apm_stop,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl6000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
@ -139,18 +223,12 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
|
||||
.get_hcmd_size = iwl5000_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl5000_build_addsta_hcmd,
|
||||
.rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
|
||||
.calc_rssi = iwl5000_calc_rssi,
|
||||
};
|
||||
|
||||
static struct iwl_ops iwl6000_ops = {
|
||||
.ucode = &iwl5000_ucode,
|
||||
.lib = &iwl6000_lib,
|
||||
.hcmd = &iwl5000_hcmd,
|
||||
.utils = &iwl6000_hcmd_utils,
|
||||
.utils = &iwl5000_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
|
||||
@ -165,7 +243,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
@ -175,6 +253,56 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000h_2abg_cfg = {
|
||||
.name = "6000 Series 2x2 ABG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000h_2bg_cfg = {
|
||||
.name = "6000 Series 2x2 BG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -188,7 +316,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
@ -198,6 +326,56 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2abg_cfg = {
|
||||
.name = "6000 Series 2x2 ABG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
.name = "6000 Series 2x2 BG",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
@ -208,7 +386,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
@ -218,6 +396,33 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
.name = "6050 Series 2x2 ABG",
|
||||
.fw_name_pre = IWL6050_FW_PRE,
|
||||
.ucode_api_max = IWL6050_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
@ -228,7 +433,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
@ -238,6 +443,10 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
@ -248,7 +457,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
@ -258,6 +467,10 @@ struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
|
85
drivers/net/wireless/iwlwifi/iwl-agn-led.c
Normal file
85
drivers/net/wireless/iwlwifi/iwl-agn-led.c
Normal file
@ -0,0 +1,85 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-led.h"
|
||||
|
||||
/* Send led command */
|
||||
static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_LEDS_CMD,
|
||||
.len = sizeof(struct iwl_led_cmd),
|
||||
.data = led_cmd,
|
||||
.flags = CMD_ASYNC,
|
||||
.callback = NULL,
|
||||
};
|
||||
u32 reg;
|
||||
|
||||
reg = iwl_read32(priv, CSR_LED_REG);
|
||||
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
|
||||
iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
|
||||
|
||||
return iwl_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
/* Set led register off */
|
||||
static int iwl_led_on_reg(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "led on\n");
|
||||
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set led register off */
|
||||
static int iwl_led_off_reg(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "LED Reg off\n");
|
||||
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct iwl_led_ops iwlagn_led_ops = {
|
||||
.cmd = iwl_send_led_cmd,
|
||||
.on = iwl_led_on_reg,
|
||||
.off = iwl_led_off_reg,
|
||||
};
|
32
drivers/net/wireless/iwlwifi/iwl-agn-led.h
Normal file
32
drivers/net/wireless/iwlwifi/iwl-agn-led.h
Normal file
@ -0,0 +1,32 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __iwl_agn_led_h__
|
||||
#define __iwl_agn_led_h__
|
||||
|
||||
extern const struct iwl_led_ops iwlagn_led_ops;
|
||||
|
||||
#endif /* __iwl_agn_led_h__ */
|
@ -171,6 +171,8 @@ struct iwl_lq_sta {
|
||||
int last_txrate_idx;
|
||||
/* last tx rate_n_flags */
|
||||
u32 last_rate_n_flags;
|
||||
/* packets destined for this STA are aggregated */
|
||||
u8 is_agg;
|
||||
};
|
||||
|
||||
static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
@ -190,84 +192,78 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
|
||||
{}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Expected throughput metrics for following rates:
|
||||
* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
|
||||
* "G" is the only table that supports CCK (the first 4 rates).
|
||||
/**
|
||||
* The following tables contain the expected throughput metrics for all rates
|
||||
*
|
||||
* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
|
||||
*
|
||||
* where invalid entries are zeros.
|
||||
*
|
||||
* CCK rates are only valid in legacy table and will only be used in G
|
||||
* (2.4 GHz) band.
|
||||
*/
|
||||
|
||||
static s32 expected_tpt_A[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
|
||||
static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
|
||||
7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
|
||||
};
|
||||
|
||||
static s32 expected_tpt_G[IWL_RATE_COUNT] = {
|
||||
7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186
|
||||
static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
|
||||
{0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */
|
||||
{0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */
|
||||
{0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */
|
||||
{0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
|
||||
};
|
||||
|
||||
static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202
|
||||
static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
|
||||
{0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
|
||||
{0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
|
||||
{0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
|
||||
{0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
|
||||
};
|
||||
|
||||
static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211
|
||||
static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
|
||||
{0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
|
||||
{0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
|
||||
{0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
|
||||
{0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251
|
||||
static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
|
||||
{0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
|
||||
{0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
|
||||
{0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
|
||||
{0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257
|
||||
static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
|
||||
{0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */
|
||||
{0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */
|
||||
{0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */
|
||||
{0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */
|
||||
};
|
||||
|
||||
static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257
|
||||
};
|
||||
|
||||
static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
|
||||
};
|
||||
|
||||
/* Expected throughput metric MIMO3 */
|
||||
static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297
|
||||
};
|
||||
|
||||
static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = {
|
||||
0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300
|
||||
static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
|
||||
{0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */
|
||||
{0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */
|
||||
{0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */
|
||||
{0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */
|
||||
};
|
||||
|
||||
/* mbps, mcs */
|
||||
const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
|
||||
{"1", ""},
|
||||
{"2", ""},
|
||||
{"5.5", ""},
|
||||
{"11", ""},
|
||||
{"6", "BPSK 1/2"},
|
||||
{"9", "BPSK 1/2"},
|
||||
{"12", "QPSK 1/2"},
|
||||
{"18", "QPSK 3/4"},
|
||||
{"24", "16QAM 1/2"},
|
||||
{"36", "16QAM 3/4"},
|
||||
{"48", "64QAM 2/3"},
|
||||
{"54", "64QAM 3/4"},
|
||||
{"60", "64QAM 5/6"}
|
||||
{ "1", "BPSK DSSS"},
|
||||
{ "2", "QPSK DSSS"},
|
||||
{"5.5", "BPSK CCK"},
|
||||
{ "11", "QPSK CCK"},
|
||||
{ "6", "BPSK 1/2"},
|
||||
{ "9", "BPSK 1/2"},
|
||||
{ "12", "QPSK 1/2"},
|
||||
{ "18", "QPSK 3/4"},
|
||||
{ "24", "16QAM 1/2"},
|
||||
{ "36", "16QAM 3/4"},
|
||||
{ "48", "64QAM 2/3"},
|
||||
{ "54", "64QAM 3/4"},
|
||||
{ "60", "64QAM 5/6"},
|
||||
};
|
||||
|
||||
#define MCS_INDEX_PER_STREAM (8)
|
||||
@ -418,6 +414,15 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
|
||||
else if (tid == IWL_AGG_ALL_TID)
|
||||
for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
|
||||
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
|
||||
if (priv->cfg->use_rts_for_ht) {
|
||||
/*
|
||||
* switch to RTS/CTS if it is the prefer protection method
|
||||
* for HT traffic
|
||||
*/
|
||||
IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
|
||||
iwlcore_commit_rxon(priv);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
|
||||
@ -435,7 +440,7 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
|
||||
* packets.
|
||||
*/
|
||||
static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
|
||||
int scale_index, s32 tpt, int retries,
|
||||
int scale_index, s32 tpt, int attempts,
|
||||
int successes)
|
||||
{
|
||||
struct iwl_rate_scale_data *window = NULL;
|
||||
@ -445,7 +450,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
|
||||
if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
/* Select data for current tx bit rate */
|
||||
/* Select window for current tx bit rate */
|
||||
window = &(windows[scale_index]);
|
||||
|
||||
/*
|
||||
@ -456,7 +461,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
|
||||
* subtract "1" from the success counter (this is the main reason
|
||||
* we keep these bitmaps!).
|
||||
*/
|
||||
while (retries > 0) {
|
||||
while (attempts > 0) {
|
||||
if (window->counter >= IWL_RATE_MAX_WINDOW) {
|
||||
|
||||
/* remove earliest */
|
||||
@ -471,17 +476,17 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
|
||||
/* Increment frames-attempted counter */
|
||||
window->counter++;
|
||||
|
||||
/* Shift bitmap by one frame (throw away oldest history),
|
||||
* OR in "1", and increment "success" if this
|
||||
* frame was successful. */
|
||||
/* Shift bitmap by one frame to throw away oldest history */
|
||||
window->data <<= 1;
|
||||
|
||||
/* Mark the most recent #successes attempts as successful */
|
||||
if (successes > 0) {
|
||||
window->success_counter++;
|
||||
window->data |= 0x1;
|
||||
successes--;
|
||||
}
|
||||
|
||||
retries--;
|
||||
attempts--;
|
||||
}
|
||||
|
||||
/* Calculate current success ratio, avoid divide-by-0! */
|
||||
@ -662,7 +667,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
|
||||
* there are no non-GF stations present in the BSS.
|
||||
*/
|
||||
static inline u8 rs_use_green(struct ieee80211_sta *sta,
|
||||
struct iwl_ht_info *ht_conf)
|
||||
struct iwl_ht_config *ht_conf)
|
||||
{
|
||||
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
|
||||
!(ht_conf->non_GF_STA_present);
|
||||
@ -811,6 +816,26 @@ out:
|
||||
return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple function to compare two rate scale table types
|
||||
*/
|
||||
static bool table_type_matches(struct iwl_scale_tbl_info *a,
|
||||
struct iwl_scale_tbl_info *b)
|
||||
{
|
||||
return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
|
||||
(a->is_SGI == b->is_SGI);
|
||||
}
|
||||
/*
|
||||
* Static function to get the expected throughput from an iwl_scale_tbl_info
|
||||
* that wraps a NULL pointer check
|
||||
*/
|
||||
static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
|
||||
{
|
||||
if (tbl->expected_tpt)
|
||||
return tbl->expected_tpt[rs_index];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* mac80211 sends us Tx status
|
||||
*/
|
||||
@ -818,21 +843,19 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int status;
|
||||
u8 retries;
|
||||
int rs_index, mac_index, index = 0;
|
||||
int legacy_success;
|
||||
int retries;
|
||||
int rs_index, mac_index, i;
|
||||
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;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl_rate_scale_data *window = NULL;
|
||||
struct iwl_rate_scale_data *search_win = NULL;
|
||||
enum mac80211_rate_control_flags mac_flags;
|
||||
u32 tx_rate;
|
||||
struct iwl_scale_tbl_info tbl_type;
|
||||
struct iwl_scale_tbl_info *curr_tbl, *search_tbl;
|
||||
u8 active_index = 0;
|
||||
struct iwl_scale_tbl_info *curr_tbl, *other_tbl;
|
||||
s32 tpt = 0;
|
||||
|
||||
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
|
||||
@ -841,30 +864,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
return;
|
||||
|
||||
/* This packet was aggregated but doesn't carry rate scale info */
|
||||
/* This packet was aggregated but doesn't carry status info */
|
||||
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
!(info->flags & IEEE80211_TX_STAT_AMPDU))
|
||||
return;
|
||||
|
||||
if (info->flags & IEEE80211_TX_STAT_AMPDU)
|
||||
retries = 0;
|
||||
else
|
||||
retries = info->status.rates[0].count - 1;
|
||||
|
||||
if (retries > 15)
|
||||
retries = 15;
|
||||
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
|
||||
!lq_sta->ibss_sta_added)
|
||||
goto out;
|
||||
|
||||
table = &lq_sta->lq;
|
||||
active_index = lq_sta->active_tbl;
|
||||
|
||||
curr_tbl = &(lq_sta->lq_info[active_index]);
|
||||
search_tbl = &(lq_sta->lq_info[(1 - active_index)]);
|
||||
window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
|
||||
search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]);
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ignore this Tx frame response if its initial rate doesn't match
|
||||
@ -874,6 +881,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
* to check "search" mode, or a prior "search" mode after we've moved
|
||||
* to a new "search" mode (which might become the new "active" mode).
|
||||
*/
|
||||
table = &lq_sta->lq;
|
||||
tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
|
||||
if (priv->band == IEEE80211_BAND_5GHZ)
|
||||
@ -892,7 +900,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
if (priv->band == IEEE80211_BAND_2GHZ)
|
||||
mac_index += IWL_FIRST_OFDM_RATE;
|
||||
}
|
||||
|
||||
/* Here we actually compare this rate to the latest LQ command */
|
||||
if ((mac_index < 0) ||
|
||||
(tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
|
||||
(tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
|
||||
@ -902,124 +910,106 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
(!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
|
||||
(rs_index != mac_index)) {
|
||||
IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate);
|
||||
/* the last LQ command could failed so the LQ in ucode not
|
||||
* the same in driver sync up
|
||||
/*
|
||||
* Since rates mis-match, the last LQ command may have failed.
|
||||
* After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
|
||||
* ... driver.
|
||||
*/
|
||||
lq_sta->missed_rate_counter++;
|
||||
if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
|
||||
lq_sta->missed_rate_counter = 0;
|
||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
lq_sta->missed_rate_counter = 0;
|
||||
/* Update frame history window with "failure" for each Tx retry. */
|
||||
while (retries) {
|
||||
/* Look up the rate and other info used for each tx attempt.
|
||||
* Each tx attempt steps one entry deeper in the rate table. */
|
||||
tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags);
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band,
|
||||
&tbl_type, &rs_index);
|
||||
|
||||
/* If type matches "search" table,
|
||||
* add failure to "search" history */
|
||||
if ((tbl_type.lq_type == search_tbl->lq_type) &&
|
||||
(tbl_type.ant_type == search_tbl->ant_type) &&
|
||||
(tbl_type.is_SGI == search_tbl->is_SGI)) {
|
||||
if (search_tbl->expected_tpt)
|
||||
tpt = search_tbl->expected_tpt[rs_index];
|
||||
else
|
||||
tpt = 0;
|
||||
rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
|
||||
|
||||
/* Else if type matches "current/active" table,
|
||||
* add failure to "current/active" history */
|
||||
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
|
||||
(tbl_type.ant_type == curr_tbl->ant_type) &&
|
||||
(tbl_type.is_SGI == curr_tbl->is_SGI)) {
|
||||
if (curr_tbl->expected_tpt)
|
||||
tpt = curr_tbl->expected_tpt[rs_index];
|
||||
else
|
||||
tpt = 0;
|
||||
rs_collect_tx_data(window, rs_index, tpt, 1, 0);
|
||||
}
|
||||
|
||||
/* If not searching for a new mode, increment failed counter
|
||||
* ... this helps determine when to start searching again */
|
||||
if (lq_sta->stay_in_tbl)
|
||||
lq_sta->total_failed++;
|
||||
--retries;
|
||||
index++;
|
||||
|
||||
/* Regardless, ignore this status info for outdated rate */
|
||||
return;
|
||||
} else
|
||||
/* Rate did match, so reset the missed_rate_counter */
|
||||
lq_sta->missed_rate_counter = 0;
|
||||
|
||||
/* Figure out if rate scale algorithm is in active or search table */
|
||||
if (table_type_matches(&tbl_type,
|
||||
&(lq_sta->lq_info[lq_sta->active_tbl]))) {
|
||||
curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
|
||||
} else if (table_type_matches(&tbl_type,
|
||||
&lq_sta->lq_info[1 - lq_sta->active_tbl])) {
|
||||
curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
|
||||
other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
} else {
|
||||
IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
|
||||
return;
|
||||
}
|
||||
window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
|
||||
|
||||
/*
|
||||
* Find (by rate) the history window to update with final Tx attempt;
|
||||
* if Tx was successful first try, use original rate,
|
||||
* else look up the rate that was, finally, successful.
|
||||
* Updating the frame history depends on whether packets were
|
||||
* aggregated.
|
||||
*
|
||||
* For aggregation, all packets were transmitted at the same rate, the
|
||||
* first index into rate scale table.
|
||||
*/
|
||||
tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags);
|
||||
lq_sta->last_rate_n_flags = tx_rate;
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
|
||||
if (info->flags & IEEE80211_TX_STAT_AMPDU) {
|
||||
tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
|
||||
&rs_index);
|
||||
tpt = get_expected_tpt(curr_tbl, rs_index);
|
||||
rs_collect_tx_data(window, rs_index, tpt,
|
||||
info->status.ampdu_ack_len,
|
||||
info->status.ampdu_ack_map);
|
||||
|
||||
/* Update frame history window with "success" if Tx got ACKed ... */
|
||||
status = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
|
||||
/* If type matches "search" table,
|
||||
* add final tx status to "search" history */
|
||||
if ((tbl_type.lq_type == search_tbl->lq_type) &&
|
||||
(tbl_type.ant_type == search_tbl->ant_type) &&
|
||||
(tbl_type.is_SGI == search_tbl->is_SGI)) {
|
||||
if (search_tbl->expected_tpt)
|
||||
tpt = search_tbl->expected_tpt[rs_index];
|
||||
else
|
||||
tpt = 0;
|
||||
if (info->flags & IEEE80211_TX_STAT_AMPDU)
|
||||
rs_collect_tx_data(search_win, rs_index, tpt,
|
||||
info->status.ampdu_ack_len,
|
||||
info->status.ampdu_ack_map);
|
||||
else
|
||||
rs_collect_tx_data(search_win, rs_index, tpt,
|
||||
1, status);
|
||||
/* Else if type matches "current/active" table,
|
||||
* add final tx status to "current/active" history */
|
||||
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
|
||||
(tbl_type.ant_type == curr_tbl->ant_type) &&
|
||||
(tbl_type.is_SGI == curr_tbl->is_SGI)) {
|
||||
if (curr_tbl->expected_tpt)
|
||||
tpt = curr_tbl->expected_tpt[rs_index];
|
||||
else
|
||||
tpt = 0;
|
||||
if (info->flags & IEEE80211_TX_STAT_AMPDU)
|
||||
rs_collect_tx_data(window, rs_index, tpt,
|
||||
info->status.ampdu_ack_len,
|
||||
info->status.ampdu_ack_map);
|
||||
else
|
||||
rs_collect_tx_data(window, rs_index, tpt,
|
||||
1, status);
|
||||
}
|
||||
|
||||
/* If not searching for new mode, increment success/failed counter
|
||||
* ... these help determine when to start searching again */
|
||||
if (lq_sta->stay_in_tbl) {
|
||||
if (info->flags & IEEE80211_TX_STAT_AMPDU) {
|
||||
/* Update success/fail counts if not searching for new mode */
|
||||
if (lq_sta->stay_in_tbl) {
|
||||
lq_sta->total_success += info->status.ampdu_ack_map;
|
||||
lq_sta->total_failed +=
|
||||
(info->status.ampdu_ack_len - info->status.ampdu_ack_map);
|
||||
} else {
|
||||
if (status)
|
||||
lq_sta->total_success++;
|
||||
lq_sta->total_failed += (info->status.ampdu_ack_len -
|
||||
info->status.ampdu_ack_map);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* For legacy, update frame history with for each Tx retry.
|
||||
*/
|
||||
retries = info->status.rates[0].count - 1;
|
||||
/* HW doesn't send more than 15 retries */
|
||||
retries = min(retries, 15);
|
||||
|
||||
/* The last transmission may have been successful */
|
||||
legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
/* Collect data for each rate used during failed TX attempts */
|
||||
for (i = 0; i <= retries; ++i) {
|
||||
tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags);
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band,
|
||||
&tbl_type, &rs_index);
|
||||
/*
|
||||
* Only collect stats if retried rate is in the same RS
|
||||
* table as active/search.
|
||||
*/
|
||||
if (table_type_matches(&tbl_type, curr_tbl))
|
||||
tpt = get_expected_tpt(curr_tbl, rs_index);
|
||||
else if (table_type_matches(&tbl_type, other_tbl))
|
||||
tpt = get_expected_tpt(other_tbl, rs_index);
|
||||
else
|
||||
lq_sta->total_failed++;
|
||||
continue;
|
||||
|
||||
/* Constants mean 1 transmission, 0 successes */
|
||||
if (i < retries)
|
||||
rs_collect_tx_data(window, rs_index, tpt, 1,
|
||||
0);
|
||||
else
|
||||
rs_collect_tx_data(window, rs_index, tpt, 1,
|
||||
legacy_success);
|
||||
}
|
||||
|
||||
/* Update success/fail counts if not searching for new mode */
|
||||
if (lq_sta->stay_in_tbl) {
|
||||
lq_sta->total_success += legacy_success;
|
||||
lq_sta->total_failed += retries + (1 - legacy_success);
|
||||
}
|
||||
}
|
||||
/* The last TX rate is cached in lq_sta; it's set in if/else above */
|
||||
lq_sta->last_rate_n_flags = tx_rate;
|
||||
|
||||
/* See if there's a better rate or modulation mode to try. */
|
||||
if (sta && sta->supp_rates[sband->band])
|
||||
rs_rate_scale_perform(priv, skb, sta, lq_sta);
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1057,43 +1047,45 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
|
||||
static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
|
||||
struct iwl_scale_tbl_info *tbl)
|
||||
{
|
||||
/* Used to choose among HT tables */
|
||||
s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
|
||||
|
||||
/* Check for invalid LQ type */
|
||||
if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
|
||||
tbl->expected_tpt = expected_tpt_legacy;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Legacy rates have only one table */
|
||||
if (is_legacy(tbl->lq_type)) {
|
||||
if (!is_a_band(tbl->lq_type))
|
||||
tbl->expected_tpt = expected_tpt_G;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_A;
|
||||
} else if (is_siso(tbl->lq_type)) {
|
||||
if (tbl->is_ht40 && !lq_sta->is_dup)
|
||||
if (tbl->is_SGI)
|
||||
tbl->expected_tpt = expected_tpt_siso40MHzSGI;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_siso40MHz;
|
||||
else if (tbl->is_SGI)
|
||||
tbl->expected_tpt = expected_tpt_siso20MHzSGI;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_siso20MHz;
|
||||
} else if (is_mimo2(tbl->lq_type)) {
|
||||
if (tbl->is_ht40 && !lq_sta->is_dup)
|
||||
if (tbl->is_SGI)
|
||||
tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_mimo2_40MHz;
|
||||
else if (tbl->is_SGI)
|
||||
tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_mimo2_20MHz;
|
||||
} else if (is_mimo3(tbl->lq_type)) {
|
||||
if (tbl->is_ht40 && !lq_sta->is_dup)
|
||||
if (tbl->is_SGI)
|
||||
tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_mimo3_40MHz;
|
||||
else if (tbl->is_SGI)
|
||||
tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI;
|
||||
else
|
||||
tbl->expected_tpt = expected_tpt_mimo3_20MHz;
|
||||
} else
|
||||
tbl->expected_tpt = expected_tpt_G;
|
||||
tbl->expected_tpt = expected_tpt_legacy;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Choose among many HT tables depending on number of streams
|
||||
* (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation
|
||||
* status */
|
||||
if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
|
||||
ht_tbl_pointer = expected_tpt_siso20MHz;
|
||||
else if (is_siso(tbl->lq_type))
|
||||
ht_tbl_pointer = expected_tpt_siso40MHz;
|
||||
else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
|
||||
ht_tbl_pointer = expected_tpt_mimo2_20MHz;
|
||||
else if (is_mimo2(tbl->lq_type))
|
||||
ht_tbl_pointer = expected_tpt_mimo2_40MHz;
|
||||
else if (is_mimo3(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
|
||||
ht_tbl_pointer = expected_tpt_mimo3_20MHz;
|
||||
else /* if (is_mimo3(tbl->lq_type)) <-- must be true */
|
||||
ht_tbl_pointer = expected_tpt_mimo3_40MHz;
|
||||
|
||||
if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */
|
||||
tbl->expected_tpt = ht_tbl_pointer[0];
|
||||
else if (tbl->is_SGI && !lq_sta->is_agg) /* SGI */
|
||||
tbl->expected_tpt = ht_tbl_pointer[1];
|
||||
else if (!tbl->is_SGI && lq_sta->is_agg) /* AGG */
|
||||
tbl->expected_tpt = ht_tbl_pointer[2];
|
||||
else /* AGG+SGI */
|
||||
tbl->expected_tpt = ht_tbl_pointer[3];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2068,6 +2060,14 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
|
||||
|
||||
tid = rs_tl_add_packet(lq_sta, hdr);
|
||||
if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) {
|
||||
tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid];
|
||||
if (tid_data->agg.state == IWL_AGG_OFF)
|
||||
lq_sta->is_agg = 0;
|
||||
else
|
||||
lq_sta->is_agg = 1;
|
||||
} else
|
||||
lq_sta->is_agg = 0;
|
||||
|
||||
/*
|
||||
* Select rate-scale / modulation-mode table to work with in
|
||||
@ -2168,10 +2168,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Else we have enough samples; calculate estimate of
|
||||
* actual average throughput */
|
||||
|
||||
/* Sanity-check TPT calculations */
|
||||
BUG_ON(window->average_tpt != ((window->success_ratio *
|
||||
tbl->expected_tpt[index] + 64) / 128));
|
||||
|
||||
@ -2681,6 +2681,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
|
||||
if (sband->band == IEEE80211_BAND_5GHZ)
|
||||
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
|
||||
lq_sta->is_agg = 0;
|
||||
|
||||
rs_initialize_lq(priv, conf, sta, lq_sta);
|
||||
}
|
||||
@ -2799,7 +2800,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
|
||||
repeat_rate--;
|
||||
}
|
||||
|
||||
lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX;
|
||||
lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
||||
lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
|
||||
lq_cmd->agg_params.agg_time_limit =
|
||||
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
|
||||
@ -2933,8 +2934,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
|
||||
((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
|
||||
desc += sprintf(buff+desc, " %s",
|
||||
(tbl->is_ht40) ? "40MHz" : "20MHz");
|
||||
desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "",
|
||||
(lq_sta->is_green) ? "GF enabled" : "");
|
||||
desc += sprintf(buff+desc, " %s %s %s\n", (tbl->is_SGI) ? "SGI" : "",
|
||||
(lq_sta->is_green) ? "GF enabled" : "",
|
||||
(lq_sta->is_agg) ? "AGG on" : "");
|
||||
}
|
||||
desc += sprintf(buff+desc, "last tx rate=0x%X\n",
|
||||
lq_sta->last_rate_n_flags);
|
||||
|
@ -115,9 +115,6 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
/* allow CTS-to-self if possible. this is relevant only for
|
||||
* 5000, but will not damage 4965 */
|
||||
priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
|
||||
|
||||
ret = iwl_check_rxon_cmd(priv);
|
||||
if (ret) {
|
||||
@ -217,6 +214,13 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
||||
"Could not send WEP static key.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* allow CTS-to-self if possible for new association.
|
||||
* this is relevant only for 5000 series and up,
|
||||
* but will not damage 4965
|
||||
*/
|
||||
priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
|
||||
|
||||
/* Apply the new configuration
|
||||
* RXON assoc doesn't clear the station table in uCode,
|
||||
*/
|
||||
@ -787,6 +791,9 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
|
||||
trace_iwlwifi_dev_rx(priv, pkt,
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
||||
/* Reclaim a command buffer only if this packet is a response
|
||||
* to a (driver-originated) command.
|
||||
* If the packet (e.g. Rx frame) originated from uCode,
|
||||
@ -1606,6 +1613,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
||||
line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
|
||||
time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
|
||||
|
||||
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
|
||||
blink1, blink2, ilink1, ilink2);
|
||||
|
||||
IWL_ERR(priv, "Desc Time "
|
||||
"data1 data2 line\n");
|
||||
IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
|
||||
@ -1654,12 +1664,14 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
ptr += sizeof(u32);
|
||||
if (mode == 0) {
|
||||
/* data, ev */
|
||||
trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
|
||||
IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
|
||||
} else {
|
||||
data = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
|
||||
time, data, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1758,6 +1770,10 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
||||
priv->active_rate = priv->rates_mask;
|
||||
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
|
||||
|
||||
/* Configure Tx antenna selection based on H/W config */
|
||||
if (priv->cfg->ops->hcmd->set_tx_ant)
|
||||
priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
|
||||
|
||||
if (iwl_is_associated(priv)) {
|
||||
struct iwl_rxon_cmd *active_rxon =
|
||||
(struct iwl_rxon_cmd *)&priv->active_rxon;
|
||||
@ -1785,7 +1801,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
||||
/* At this point, the NIC is initialized and operational */
|
||||
iwl_rf_kill_ct_config(priv);
|
||||
|
||||
iwl_leds_register(priv);
|
||||
iwl_leds_init(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
|
||||
set_bit(STATUS_READY, &priv->status);
|
||||
@ -1823,8 +1839,6 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
if (!exit_pending)
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
iwl_leds_unregister(priv);
|
||||
|
||||
iwl_clear_stations_table(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
@ -2323,6 +2337,8 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
}
|
||||
|
||||
iwl_led_start(priv);
|
||||
|
||||
out:
|
||||
priv->is_open = 1;
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
@ -2794,6 +2810,40 @@ static ssize_t show_statistics(struct device *d,
|
||||
|
||||
static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
|
||||
|
||||
static ssize_t show_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
|
||||
}
|
||||
|
||||
static ssize_t store_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "Input is not in decimal form.\n");
|
||||
else {
|
||||
if (!iwl_is_associated(priv))
|
||||
priv->cfg->use_rts_for_ht = val ? true : false;
|
||||
else
|
||||
IWL_ERR(priv, "Sta associated with AP - "
|
||||
"Change protection mechanism is not allowed\n");
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
|
||||
show_rts_ht_protection, store_rts_ht_protection);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
@ -2850,6 +2900,7 @@ static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_statistics.attr,
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
&dev_attr_rts_ht_protection.attr,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
@ -3215,20 +3266,51 @@ static struct pci_device_id iwl_hw_card_ids[] = {
|
||||
/* 5150 Wifi/WiMax */
|
||||
{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
|
||||
/* 6000/6050 Series */
|
||||
{IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)},
|
||||
|
||||
/* 6x00 Series */
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1301, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1321, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1326, iwl6000h_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1306, iwl6000h_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008D, 0x1307, iwl6000h_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008E, 0x1311, iwl6000h_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008E, 0x1316, iwl6000h_2abg_cfg)},
|
||||
|
||||
{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
|
||||
|
||||
/* 6x50 WiFi/WiMax Series */
|
||||
{IWL_PCI_DEVICE(0x0086, 0x1101, iwl6050_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0086, 0x1121, iwl6050_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0088, 0x1111, iwl6050_3agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
|
||||
|
||||
/* 1000 Series WiFi */
|
||||
{IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
|
||||
#endif /* CONFIG_IWL5000 */
|
||||
|
||||
{0}
|
||||
@ -3283,9 +3365,9 @@ module_exit(iwl_exit);
|
||||
module_init(iwl_init);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
module_param_named(debug50, iwl_debug_level, uint, 0444);
|
||||
module_param_named(debug50, iwl_debug_level, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)");
|
||||
module_param_named(debug, iwl_debug_level, uint, 0644);
|
||||
module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "debug output mask");
|
||||
#endif
|
||||
|
||||
|
@ -516,7 +516,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
|
||||
for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
|
||||
data->nrg_silence_rssi[i] = 0;
|
||||
|
||||
data->auto_corr_ofdm = 90;
|
||||
data->auto_corr_ofdm = ranges->auto_corr_min_ofdm;
|
||||
data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
|
||||
data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1;
|
||||
data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
|
||||
@ -643,6 +643,15 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sensitivity_calibration);
|
||||
|
||||
static inline u8 find_first_chain(u8 mask)
|
||||
{
|
||||
if (mask & ANT_A)
|
||||
return CHAIN_A;
|
||||
if (mask & ANT_B)
|
||||
return CHAIN_B;
|
||||
return CHAIN_C;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate 20 beacons of signal and noise statistics for each of
|
||||
* 3 receivers/antennas/rx-chains, then figure out:
|
||||
@ -675,14 +684,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
|
||||
u8 num_tx_chains;
|
||||
unsigned long flags;
|
||||
struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
|
||||
u8 first_chain;
|
||||
|
||||
if (priv->disable_chain_noise_cal)
|
||||
return;
|
||||
|
||||
data = &(priv->chain_noise_data);
|
||||
|
||||
/* Accumulate just the first 20 beacons after the first association,
|
||||
* then we're done forever. */
|
||||
/*
|
||||
* Accumulate just the first "chain_noise_num_beacons" after
|
||||
* the first association, then we're done forever.
|
||||
*/
|
||||
if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
|
||||
if (data->state == IWL_CHAIN_NOISE_ALIVE)
|
||||
IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n");
|
||||
@ -710,7 +722,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Accumulate beacon statistics values across 20 beacons */
|
||||
/*
|
||||
* Accumulate beacon statistics values across
|
||||
* "chain_noise_num_beacons"
|
||||
*/
|
||||
chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
|
||||
IN_BAND_FILTER;
|
||||
chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
|
||||
@ -741,16 +756,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
|
||||
IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
|
||||
chain_noise_a, chain_noise_b, chain_noise_c);
|
||||
|
||||
/* If this is the 20th beacon, determine:
|
||||
/* If this is the "chain_noise_num_beacons", determine:
|
||||
* 1) Disconnected antennas (using signal strengths)
|
||||
* 2) Differential gain (using silence noise) to balance receivers */
|
||||
if (data->beacon_count != CAL_NUM_OF_BEACONS)
|
||||
if (data->beacon_count != priv->cfg->chain_noise_num_beacons)
|
||||
return;
|
||||
|
||||
/* Analyze signal for disconnected antenna */
|
||||
average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS;
|
||||
average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS;
|
||||
average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS;
|
||||
average_sig[0] =
|
||||
(data->chain_signal_a) / priv->cfg->chain_noise_num_beacons;
|
||||
average_sig[1] =
|
||||
(data->chain_signal_b) / priv->cfg->chain_noise_num_beacons;
|
||||
average_sig[2] =
|
||||
(data->chain_signal_c) / priv->cfg->chain_noise_num_beacons;
|
||||
|
||||
if (average_sig[0] >= average_sig[1]) {
|
||||
max_average_sig = average_sig[0];
|
||||
@ -803,13 +821,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
|
||||
/* there is a Tx antenna connected */
|
||||
break;
|
||||
if (num_tx_chains == priv->hw_params.tx_chains_num &&
|
||||
data->disconn_array[i]) {
|
||||
/* This is the last TX antenna and is also
|
||||
* disconnected connect it anyway */
|
||||
data->disconn_array[i] = 0;
|
||||
active_chains |= ant_msk;
|
||||
IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - "
|
||||
"declare %d as connected\n", i);
|
||||
data->disconn_array[i]) {
|
||||
/*
|
||||
* If all chains are disconnected
|
||||
* connect the first valid tx chain
|
||||
*/
|
||||
first_chain =
|
||||
find_first_chain(priv->cfg->valid_tx_ant);
|
||||
data->disconn_array[first_chain] = 0;
|
||||
active_chains |= BIT(first_chain);
|
||||
IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
|
||||
first_chain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -820,9 +842,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
|
||||
active_chains);
|
||||
|
||||
/* Analyze noise for rx balance */
|
||||
average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS);
|
||||
average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS);
|
||||
average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS);
|
||||
average_noise[0] =
|
||||
((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons);
|
||||
average_noise[1] =
|
||||
((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons);
|
||||
average_noise[2] =
|
||||
((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons);
|
||||
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
if (!(data->disconn_array[i]) &&
|
||||
@ -843,7 +868,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
|
||||
|
||||
if (priv->cfg->ops->utils->gain_computation)
|
||||
priv->cfg->ops->utils->gain_computation(priv, average_noise,
|
||||
min_average_noise_antenna_i, min_average_noise);
|
||||
min_average_noise_antenna_i, min_average_noise,
|
||||
find_first_chain(priv->cfg->valid_rx_ant));
|
||||
|
||||
/* Some power changes may have been made during the calibration.
|
||||
* Update and commit the RXON
|
||||
|
@ -148,7 +148,7 @@ enum {
|
||||
QUIET_NOTIFICATION = 0x96, /* not used */
|
||||
REPLY_TX_PWR_TABLE_CMD = 0x97,
|
||||
REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */
|
||||
TX_ANT_CONFIGURATION_CMD = 0x98, /* not used */
|
||||
TX_ANT_CONFIGURATION_CMD = 0x98,
|
||||
MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */
|
||||
|
||||
/* Bluetooth device coexistence config command */
|
||||
@ -411,6 +411,16 @@ struct iwl5000_tx_power_dbm_cmd {
|
||||
u8 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* Command TX_ANT_CONFIGURATION_CMD = 0x98
|
||||
* This command is used to configure valid Tx antenna.
|
||||
* By default uCode concludes the valid antenna according to the radio flavor.
|
||||
* This command enables the driver to override/modify this conclusion.
|
||||
*/
|
||||
struct iwl_tx_ant_config_cmd {
|
||||
__le32 valid;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/******************************************************************************
|
||||
* (0a)
|
||||
* Alive and Error Commands & Responses:
|
||||
|
@ -607,8 +607,7 @@ EXPORT_SYMBOL(iwlcore_free_geos);
|
||||
static bool is_single_rx_stream(struct iwl_priv *priv)
|
||||
{
|
||||
return !priv->current_ht_config.is_ht ||
|
||||
((priv->current_ht_config.mcs.rx_mask[1] == 0) &&
|
||||
(priv->current_ht_config.mcs.rx_mask[2] == 0));
|
||||
priv->current_ht_config.single_chain_sufficient;
|
||||
}
|
||||
|
||||
static u8 iwl_is_channel_extension(struct iwl_priv *priv,
|
||||
@ -634,10 +633,9 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
|
||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf)
|
||||
{
|
||||
struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
|
||||
if ((!iwl_ht_conf->is_ht) ||
|
||||
(iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ))
|
||||
if (!ht_conf->is_ht || !ht_conf->is_40mhz)
|
||||
return 0;
|
||||
|
||||
/* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
||||
@ -653,7 +651,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
#endif
|
||||
return iwl_is_channel_extension(priv, priv->band,
|
||||
le16_to_cpu(priv->staging_rxon.channel),
|
||||
iwl_ht_conf->extension_chan_offset);
|
||||
ht_conf->extension_chan_offset);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
|
||||
|
||||
@ -877,11 +875,11 @@ u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
|
||||
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
|
||||
{
|
||||
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
|
||||
|
||||
if (!ht_info->is_ht) {
|
||||
if (!ht_conf->is_ht) {
|
||||
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
|
||||
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
|
||||
RXON_FLG_HT40_PROT_MSK |
|
||||
@ -892,7 +890,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
|
||||
/* FIXME: if the definition of ht_protection changed, the "translation"
|
||||
* will be needed for rxon->flags
|
||||
*/
|
||||
rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
|
||||
rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
|
||||
|
||||
/* Set up channel bandwidth:
|
||||
* 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
|
||||
@ -901,10 +899,10 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
|
||||
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
|
||||
if (iwl_is_ht40_tx_allowed(priv, NULL)) {
|
||||
/* pure ht40 */
|
||||
if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
|
||||
if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
|
||||
rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
|
||||
/* Note: control channel is opposite of extension channel */
|
||||
switch (ht_info->extension_chan_offset) {
|
||||
switch (ht_conf->extension_chan_offset) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
|
||||
break;
|
||||
@ -914,7 +912,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
|
||||
}
|
||||
} else {
|
||||
/* Note: control channel is opposite of extension channel */
|
||||
switch (ht_info->extension_chan_offset) {
|
||||
switch (ht_conf->extension_chan_offset) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
|
||||
rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
|
||||
@ -937,14 +935,10 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X "
|
||||
"rxon flags 0x%X operation mode :0x%X "
|
||||
IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
|
||||
"extension channel offset 0x%x\n",
|
||||
ht_info->mcs.rx_mask[0],
|
||||
ht_info->mcs.rx_mask[1],
|
||||
ht_info->mcs.rx_mask[2],
|
||||
le32_to_cpu(rxon->flags), ht_info->ht_protection,
|
||||
ht_info->extension_chan_offset);
|
||||
le32_to_cpu(rxon->flags), ht_conf->ht_protection,
|
||||
ht_conf->extension_chan_offset);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_ht);
|
||||
@ -954,47 +948,37 @@ EXPORT_SYMBOL(iwl_set_rxon_ht);
|
||||
#define IWL_NUM_IDLE_CHAINS_DUAL 2
|
||||
#define IWL_NUM_IDLE_CHAINS_SINGLE 1
|
||||
|
||||
/* Determine how many receiver/antenna chains to use.
|
||||
* More provides better reception via diversity. Fewer saves power.
|
||||
/*
|
||||
* Determine how many receiver/antenna chains to use.
|
||||
*
|
||||
* More provides better reception via diversity. Fewer saves power
|
||||
* at the expense of throughput, but only when not in powersave to
|
||||
* start with.
|
||||
*
|
||||
* MIMO (dual stream) requires at least 2, but works better with 3.
|
||||
* This does not determine *which* chains to use, just how many.
|
||||
*/
|
||||
static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
||||
{
|
||||
bool is_single = is_single_rx_stream(priv);
|
||||
bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
|
||||
|
||||
/* # of Rx chains to use when expecting MIMO. */
|
||||
if (is_single || (!is_cam && (priv->current_ht_config.sm_ps ==
|
||||
WLAN_HT_CAP_SM_PS_STATIC)))
|
||||
if (is_single_rx_stream(priv))
|
||||
return IWL_NUM_RX_CHAINS_SINGLE;
|
||||
else
|
||||
return IWL_NUM_RX_CHAINS_MULTIPLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we are in power saving, there's no difference between
|
||||
* using multiple chains or just a single chain, but due to the
|
||||
* lack of SM PS we lose a lot of throughput if we use just a
|
||||
* single chain.
|
||||
*
|
||||
* Therefore, use the active count here (which will use multiple
|
||||
* chains unless connected to a legacy AP).
|
||||
*/
|
||||
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
|
||||
{
|
||||
int idle_cnt;
|
||||
bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
|
||||
/* # Rx chains when idling and maybe trying to save power */
|
||||
switch (priv->current_ht_config.sm_ps) {
|
||||
case WLAN_HT_CAP_SM_PS_STATIC:
|
||||
case WLAN_HT_CAP_SM_PS_DYNAMIC:
|
||||
idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
|
||||
IWL_NUM_IDLE_CHAINS_SINGLE;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DISABLED:
|
||||
idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_INVALID:
|
||||
default:
|
||||
IWL_ERR(priv, "invalid mimo ps mode %d\n",
|
||||
priv->current_ht_config.sm_ps);
|
||||
WARN_ON(1);
|
||||
idle_cnt = -1;
|
||||
break;
|
||||
}
|
||||
return idle_cnt;
|
||||
return active_cnt;
|
||||
}
|
||||
|
||||
/* up to 4 chains */
|
||||
@ -1004,7 +988,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
|
||||
res = (chain_bitmap & BIT(0)) >> 0;
|
||||
res += (chain_bitmap & BIT(1)) >> 1;
|
||||
res += (chain_bitmap & BIT(2)) >> 2;
|
||||
res += (chain_bitmap & BIT(4)) >> 4;
|
||||
res += (chain_bitmap & BIT(3)) >> 3;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1345,6 +1329,42 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_irq_handle_error);
|
||||
|
||||
int iwl_apm_stop_master(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* set stop master bit */
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
|
||||
|
||||
iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
|
||||
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
IWL_DEBUG_INFO(priv, "stop master\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_apm_stop_master);
|
||||
|
||||
void iwl_apm_stop(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
udelay(10);
|
||||
/* clear "init complete" move adapter D0A* --> D0U state */
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_apm_stop);
|
||||
|
||||
void iwl_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
@ -1494,8 +1514,6 @@ int iwl_init_drv(struct iwl_priv *priv)
|
||||
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
|
||||
priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
|
||||
|
||||
/* Choose which receivers/antennas to use */
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
@ -2227,42 +2245,58 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
EXPORT_SYMBOL(iwl_mac_conf_tx);
|
||||
|
||||
static void iwl_ht_conf(struct iwl_priv *priv,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *ht_conf;
|
||||
struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: \n");
|
||||
|
||||
if (!iwl_conf->is_ht)
|
||||
if (!ht_conf->is_ht)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* It is totally wrong to base global information on something
|
||||
* that is valid only when associated, alas, this driver works
|
||||
* that way and I don't know how to fix it.
|
||||
*/
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(priv->hw, priv->bssid);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
ht_conf = &sta->ht_cap;
|
||||
|
||||
iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
|
||||
|
||||
memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
|
||||
|
||||
iwl_conf->ht_protection =
|
||||
ht_conf->ht_protection =
|
||||
bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
|
||||
iwl_conf->non_GF_STA_present =
|
||||
ht_conf->non_GF_STA_present =
|
||||
!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
|
||||
|
||||
rcu_read_unlock();
|
||||
ht_conf->single_chain_sufficient = false;
|
||||
|
||||
switch (priv->iw_mode) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(priv->hw, priv->bssid);
|
||||
if (sta) {
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
int maxstreams;
|
||||
|
||||
maxstreams = (ht_cap->mcs.tx_params &
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
|
||||
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
|
||||
maxstreams += 1;
|
||||
|
||||
if ((ht_cap->mcs.rx_mask[1] == 0) &&
|
||||
(ht_cap->mcs.rx_mask[2] == 0))
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
if (maxstreams <= 1)
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
} else {
|
||||
/*
|
||||
* If at all, this can only happen through a race
|
||||
* when the AP disconnects us while we're still
|
||||
* setting up the connection, in that case mac80211
|
||||
* will soon tell us about that.
|
||||
*/
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
@ -2386,6 +2420,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
priv->timestamp = bss_conf->timestamp;
|
||||
priv->assoc_capability = bss_conf->assoc_capability;
|
||||
|
||||
iwl_led_associate(priv);
|
||||
|
||||
/*
|
||||
* We have just associated, don't start scan too early
|
||||
* leave time for EAPOL exchange to complete.
|
||||
@ -2396,9 +2432,10 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
|
||||
if (!iwl_is_rfkill(priv))
|
||||
priv->cfg->ops->lib->post_associate(priv);
|
||||
} else
|
||||
} else {
|
||||
priv->assoc_id = 0;
|
||||
|
||||
iwl_led_disassociate(priv);
|
||||
}
|
||||
}
|
||||
|
||||
if (changes && iwl_is_associated(priv) && priv->assoc_id) {
|
||||
@ -2569,7 +2606,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct iwl_ht_info *ht_conf = &priv->current_ht_config;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
u16 ch;
|
||||
@ -2619,21 +2656,18 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ht_conf->supported_chan_width =
|
||||
IWL_CHANNEL_WIDTH_40MHZ;
|
||||
ht_conf->is_40mhz = true;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ht_conf->supported_chan_width =
|
||||
IWL_CHANNEL_WIDTH_40MHZ;
|
||||
ht_conf->is_40mhz = true;
|
||||
} else {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
ht_conf->supported_chan_width =
|
||||
IWL_CHANNEL_WIDTH_20MHZ;
|
||||
ht_conf->is_40mhz = false;
|
||||
}
|
||||
} else
|
||||
ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ;
|
||||
ht_conf->is_40mhz = false;
|
||||
/* Default to no protection. Protection mode will later be set
|
||||
* from BSS config in iwl_ht_conf */
|
||||
ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
|
||||
@ -2655,7 +2689,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
iwl_set_rate(priv);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_PS) {
|
||||
if (changed & (IEEE80211_CONF_CHANGE_PS |
|
||||
IEEE80211_CONF_CHANGE_IDLE)) {
|
||||
ret = iwl_power_update_mode(priv, false);
|
||||
if (ret)
|
||||
IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
|
||||
@ -2739,7 +2774,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
|
||||
memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_reset_qos(priv);
|
||||
|
@ -89,6 +89,7 @@ struct iwl_hcmd_ops {
|
||||
int (*rxon_assoc)(struct iwl_priv *priv);
|
||||
int (*commit_rxon)(struct iwl_priv *priv);
|
||||
void (*set_rxon_chain)(struct iwl_priv *priv);
|
||||
int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
|
||||
};
|
||||
|
||||
struct iwl_hcmd_utils_ops {
|
||||
@ -97,7 +98,8 @@ struct iwl_hcmd_utils_ops {
|
||||
void (*gain_computation)(struct iwl_priv *priv,
|
||||
u32 *average_noise,
|
||||
u16 min_average_noise_antennat_i,
|
||||
u32 min_average_noise);
|
||||
u32 min_average_noise,
|
||||
u8 default_chain);
|
||||
void (*chain_noise_reset)(struct iwl_priv *priv);
|
||||
void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info,
|
||||
__le32 *tx_flags);
|
||||
@ -185,11 +187,18 @@ struct iwl_lib_ops {
|
||||
struct iwl_temp_ops temp_ops;
|
||||
};
|
||||
|
||||
struct iwl_led_ops {
|
||||
int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
|
||||
int (*on)(struct iwl_priv *priv);
|
||||
int (*off)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_ops {
|
||||
const struct iwl_ucode_ops *ucode;
|
||||
const struct iwl_lib_ops *lib;
|
||||
const struct iwl_hcmd_ops *hcmd;
|
||||
const struct iwl_hcmd_utils_ops *utils;
|
||||
const struct iwl_led_ops *led;
|
||||
};
|
||||
|
||||
struct iwl_mod_params {
|
||||
@ -213,6 +222,11 @@ struct iwl_mod_params {
|
||||
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
||||
* @max_ll_items: max number of OTP blocks
|
||||
* @shadow_ram_support: shadow support for OTP memory
|
||||
* @led_compensation: compensate on the led on/off time per HW according
|
||||
* to the deviation to achieve the desired led frequency.
|
||||
* The detail algorithm is described in iwl-led.c
|
||||
* @use_rts_for_ht: use rts/cts protection for HT traffic
|
||||
* @chain_noise_num_beacons: number of beacons used to compute chain noise
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||
@ -254,7 +268,11 @@ struct iwl_cfg {
|
||||
const u16 max_ll_items;
|
||||
const bool shadow_ram_support;
|
||||
const bool ht_greenfield_support;
|
||||
u16 led_compensation;
|
||||
const bool broken_powersave;
|
||||
bool use_rts_for_ht;
|
||||
int chain_noise_num_beacons;
|
||||
const bool supports_idle;
|
||||
};
|
||||
|
||||
/***************************
|
||||
@ -273,7 +291,7 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
|
||||
int iwl_full_rxon_required(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);
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band);
|
||||
@ -569,6 +587,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
|
||||
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
|
||||
#define STATUS_INT_ENABLED 2
|
||||
#define STATUS_RF_KILL_HW 3
|
||||
#define STATUS_CT_KILL 4
|
||||
#define STATUS_INIT 5
|
||||
#define STATUS_ALIVE 6
|
||||
#define STATUS_READY 7
|
||||
@ -613,6 +632,11 @@ static inline int iwl_is_rfkill(struct iwl_priv *priv)
|
||||
return iwl_is_rfkill_hw(priv);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ctkill(struct iwl_priv *priv)
|
||||
{
|
||||
return test_bit(STATUS_CT_KILL, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
|
||||
{
|
||||
|
||||
@ -634,6 +658,8 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_stop_master(struct iwl_priv *priv);
|
||||
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv);
|
||||
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
|
||||
@ -653,5 +679,4 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
|
||||
{
|
||||
return priv->hw->wiphy->bands[band];
|
||||
}
|
||||
|
||||
#endif /* __iwl_core_h__ */
|
||||
|
@ -230,13 +230,18 @@
|
||||
|
||||
/* EEPROM GP */
|
||||
#define CSR_EEPROM_GP_VALID_MSK (0x00000007)
|
||||
#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
|
||||
#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
|
||||
#define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */
|
||||
#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */
|
||||
#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */
|
||||
#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */
|
||||
|
||||
/* EEPROM signature */
|
||||
#define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000)
|
||||
#define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001)
|
||||
#define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002)
|
||||
#define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004)
|
||||
|
||||
/* CSR GIO */
|
||||
#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002)
|
||||
|
||||
|
@ -84,9 +84,7 @@ struct iwl_debugfs {
|
||||
struct dentry *file_interrupt;
|
||||
struct dentry *file_qos;
|
||||
struct dentry *file_thermal_throttling;
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
struct dentry *file_led;
|
||||
#endif
|
||||
struct dentry *file_disable_ht40;
|
||||
struct dentry *file_sleep_level_override;
|
||||
struct dentry *file_current_sleep_command;
|
||||
|
@ -383,6 +383,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
|
||||
int pos = 0, ofs = 0, buf_size = 0;
|
||||
const u8 *ptr;
|
||||
char *buf;
|
||||
u16 eeprom_ver;
|
||||
size_t eeprom_len = priv->cfg->eeprom_size;
|
||||
buf_size = 4 * eeprom_len + 256;
|
||||
|
||||
@ -403,9 +404,11 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
|
||||
IWL_ERR(priv, "Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
|
||||
"version: 0x%x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM");
|
||||
? "OTP" : "EEPROM", eeprom_ver);
|
||||
for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
|
||||
pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
|
||||
hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
|
||||
@ -532,6 +535,8 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
|
||||
test_bit(STATUS_INT_ENABLED, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
|
||||
test_bit(STATUS_CT_KILL, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
|
||||
test_bit(STATUS_INIT, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
|
||||
@ -672,7 +677,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -697,7 +701,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
@ -861,9 +864,7 @@ DEBUGFS_READ_FILE_OPS(channels);
|
||||
DEBUGFS_READ_FILE_OPS(status);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
|
||||
DEBUGFS_READ_FILE_OPS(qos);
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
DEBUGFS_READ_FILE_OPS(led);
|
||||
#endif
|
||||
DEBUGFS_READ_FILE_OPS(thermal_throttling);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
|
||||
@ -1661,9 +1662,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
DEBUGFS_ADD_FILE(status, data);
|
||||
DEBUGFS_ADD_FILE(interrupt, data);
|
||||
DEBUGFS_ADD_FILE(qos, data);
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
DEBUGFS_ADD_FILE(led, data);
|
||||
#endif
|
||||
DEBUGFS_ADD_FILE(sleep_level_override, data);
|
||||
DEBUGFS_ADD_FILE(current_sleep_command, data);
|
||||
DEBUGFS_ADD_FILE(thermal_throttling, data);
|
||||
@ -1716,9 +1715,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
|
||||
#endif
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-4965-hw.h"
|
||||
#include "iwl-3945-hw.h"
|
||||
#include "iwl-3945-led.h"
|
||||
#include "iwl-led.h"
|
||||
#include "iwl-power.h"
|
||||
#include "iwl-agn-rs.h"
|
||||
@ -57,17 +56,22 @@ extern struct iwl_cfg iwl5100_bg_cfg;
|
||||
extern struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern struct iwl_cfg iwl6000h_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000h_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000h_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6050_3agn_cfg;
|
||||
extern struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern struct iwl_cfg iwl1000_bg_cfg;
|
||||
|
||||
struct iwl_tx_queue;
|
||||
|
||||
/* shared structures from iwl-5000.c */
|
||||
extern struct iwl_mod_params iwl50_mod_params;
|
||||
extern struct iwl_ops iwl5000_ops;
|
||||
extern struct iwl_ucode_ops iwl5000_ucode;
|
||||
extern struct iwl_lib_ops iwl5000_lib;
|
||||
extern struct iwl_hcmd_ops iwl5000_hcmd;
|
||||
@ -82,7 +86,6 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
|
||||
extern int iwl5000_calc_rssi(struct iwl_priv *priv,
|
||||
struct iwl_rx_phy_res *rx_resp);
|
||||
extern int iwl5000_apm_init(struct iwl_priv *priv);
|
||||
extern void iwl5000_apm_stop(struct iwl_priv *priv);
|
||||
extern int iwl5000_apm_reset(struct iwl_priv *priv);
|
||||
extern void iwl5000_nic_config(struct iwl_priv *priv);
|
||||
extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv);
|
||||
@ -502,12 +505,11 @@ union iwl_ht_rate_supp {
|
||||
#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
|
||||
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
|
||||
|
||||
struct iwl_ht_info {
|
||||
struct iwl_ht_config {
|
||||
/* self configuration data */
|
||||
u8 is_ht;
|
||||
u8 supported_chan_width;
|
||||
u8 sm_ps;
|
||||
struct ieee80211_mcs_info mcs;
|
||||
bool is_ht;
|
||||
bool is_40mhz;
|
||||
bool single_chain_sufficient;
|
||||
/* BSS related data */
|
||||
u8 extension_chan_offset;
|
||||
u8 ht_protection;
|
||||
@ -726,9 +728,6 @@ struct iwl_dma_ptr {
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define IWL_CHANNEL_WIDTH_20MHZ 0
|
||||
#define IWL_CHANNEL_WIDTH_40MHZ 1
|
||||
|
||||
#define IWL_OPERATION_MODE_AUTO 0
|
||||
#define IWL_OPERATION_MODE_HT_ONLY 1
|
||||
#define IWL_OPERATION_MODE_MIXED 2
|
||||
@ -741,7 +740,8 @@ struct iwl_dma_ptr {
|
||||
|
||||
/* Sensitivity and chain noise calibration */
|
||||
#define INITIALIZATION_VALUE 0xFFFF
|
||||
#define CAL_NUM_OF_BEACONS 20
|
||||
#define IWL4965_CAL_NUM_BEACONS 20
|
||||
#define IWL_CAL_NUM_BEACONS 16
|
||||
#define MAXIMUM_ALLOWED_PATHLOSS 15
|
||||
|
||||
#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3
|
||||
@ -1063,14 +1063,11 @@ struct iwl_priv {
|
||||
struct iwl_init_alive_resp card_alive_init;
|
||||
struct iwl_alive_resp card_alive;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
unsigned long last_blink_time;
|
||||
u8 last_blink_rate;
|
||||
u8 allow_blinking;
|
||||
u64 led_tpt;
|
||||
struct iwl_led led[IWL_LED_TRG_MAX];
|
||||
unsigned int rxtxpackets;
|
||||
#endif
|
||||
|
||||
u16 active_rate;
|
||||
u16 active_rate_basic;
|
||||
|
||||
@ -1080,7 +1077,7 @@ struct iwl_priv {
|
||||
struct iwl_chain_noise_data chain_noise_data;
|
||||
__le16 sensitivity_tbl[HD_TABLE_SIZE];
|
||||
|
||||
struct iwl_ht_info current_ht_config;
|
||||
struct iwl_ht_config current_ht_config;
|
||||
u8 last_phy_res[100];
|
||||
|
||||
/* Rate scaling data */
|
||||
|
13
drivers/net/wireless/iwlwifi/iwl-devtrace.c
Normal file
13
drivers/net/wireless/iwlwifi/iwl-devtrace.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
/* sparse doesn't like tracepoint macros */
|
||||
#ifndef __CHECKER__
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "iwl-devtrace.h"
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
|
||||
#endif
|
178
drivers/net/wireless/iwlwifi/iwl-devtrace.h
Normal file
178
drivers/net/wireless/iwlwifi/iwl-devtrace.h
Normal file
@ -0,0 +1,178 @@
|
||||
#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define __IWLWIFI_DEVICE_TRACE
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include "iwl-dev.h"
|
||||
|
||||
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#endif
|
||||
|
||||
#define PRIV_ENTRY __field(struct iwl_priv *, priv)
|
||||
#define PRIV_ASSIGN __entry->priv = priv
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM iwlwifi
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ioread32,
|
||||
TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
|
||||
TP_ARGS(priv, offs, val),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
__field(u32, offs)
|
||||
__field(u32, val)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
__entry->offs = offs;
|
||||
__entry->val = val;
|
||||
),
|
||||
TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_iowrite32,
|
||||
TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
|
||||
TP_ARGS(priv, offs, val),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
__field(u32, offs)
|
||||
__field(u32, val)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
__entry->offs = offs;
|
||||
__entry->val = val;
|
||||
),
|
||||
TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_hcmd,
|
||||
TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags),
|
||||
TP_ARGS(priv, hcmd, len, flags),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
__dynamic_array(u8, hcmd, len)
|
||||
__field(u32, flags)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
memcpy(__get_dynamic_array(hcmd), hcmd, len);
|
||||
__entry->flags = flags;
|
||||
),
|
||||
TP_printk("[%p] hcmd %#.2x (%ssync)",
|
||||
__entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0],
|
||||
__entry->flags & CMD_ASYNC ? "a" : "")
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_rx,
|
||||
TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len),
|
||||
TP_ARGS(priv, rxbuf, len),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
__dynamic_array(u8, rxbuf, len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
|
||||
),
|
||||
TP_printk("[%p] RX cmd %#.2x",
|
||||
__entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_tx,
|
||||
TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen,
|
||||
void *buf0, size_t buf0_len,
|
||||
void *buf1, size_t buf1_len),
|
||||
TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
|
||||
__field(size_t, framelen)
|
||||
__dynamic_array(u8, tfd, tfdlen)
|
||||
|
||||
/*
|
||||
* Do not insert between or below these items,
|
||||
* we want to keep the frame together (except
|
||||
* for the possible padding).
|
||||
*/
|
||||
__dynamic_array(u8, buf0, buf0_len)
|
||||
__dynamic_array(u8, buf1, buf1_len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
__entry->framelen = buf0_len + buf1_len;
|
||||
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
|
||||
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
|
||||
memcpy(__get_dynamic_array(buf1), buf1, buf0_len);
|
||||
),
|
||||
TP_printk("[%p] TX %.2x (%zu bytes)",
|
||||
__entry->priv,
|
||||
((u8 *)__get_dynamic_array(buf0))[0],
|
||||
__entry->framelen)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ucode_error,
|
||||
TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time,
|
||||
u32 data1, u32 data2, u32 line, u32 blink1,
|
||||
u32 blink2, u32 ilink1, u32 ilink2),
|
||||
TP_ARGS(priv, desc, time, data1, data2, line,
|
||||
blink1, blink2, ilink1, ilink2),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
__field(u32, desc)
|
||||
__field(u32, time)
|
||||
__field(u32, data1)
|
||||
__field(u32, data2)
|
||||
__field(u32, line)
|
||||
__field(u32, blink1)
|
||||
__field(u32, blink2)
|
||||
__field(u32, ilink1)
|
||||
__field(u32, ilink2)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
__entry->desc = desc;
|
||||
__entry->time = time;
|
||||
__entry->data1 = data1;
|
||||
__entry->data2 = data2;
|
||||
__entry->line = line;
|
||||
__entry->blink1 = blink1;
|
||||
__entry->blink2 = blink2;
|
||||
__entry->ilink1 = ilink1;
|
||||
__entry->ilink2 = ilink2;
|
||||
),
|
||||
TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
|
||||
"blink 0x%05X 0x%05X ilink 0x%05X 0x%05X",
|
||||
__entry->priv, __entry->desc, __entry->time, __entry->data1,
|
||||
__entry->data2, __entry->line, __entry->blink1,
|
||||
__entry->blink2, __entry->ilink1, __entry->ilink2)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ucode_event,
|
||||
TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
|
||||
TP_ARGS(priv, time, data, ev),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
|
||||
__field(u32, time)
|
||||
__field(u32, data)
|
||||
__field(u32, ev)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
__entry->time = time;
|
||||
__entry->data = data;
|
||||
__entry->ev = ev;
|
||||
),
|
||||
TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
|
||||
__entry->priv, __entry->time, __entry->data, __entry->ev)
|
||||
);
|
||||
#endif /* __IWLWIFI_DEVICE_TRACE */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE iwl-devtrace
|
||||
#include <trace/define_trace.h>
|
@ -215,12 +215,35 @@ static const struct iwl_txpwr_section enhinfo[] = {
|
||||
|
||||
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
{
|
||||
u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
|
||||
if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
|
||||
IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
|
||||
return -ENOENT;
|
||||
u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
|
||||
int ret = 0;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp);
|
||||
switch (gp) {
|
||||
case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP:
|
||||
if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) {
|
||||
IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n",
|
||||
gp);
|
||||
ret = -ENOENT;
|
||||
}
|
||||
break;
|
||||
case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
|
||||
case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
|
||||
if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) {
|
||||
IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp);
|
||||
ret = -ENOENT;
|
||||
}
|
||||
break;
|
||||
case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP:
|
||||
default:
|
||||
IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, "
|
||||
"EEPROM_GP=0x%08x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM", gp);
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
|
||||
|
||||
@ -283,7 +306,8 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
|
||||
|
||||
/* See if we got it */
|
||||
ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
|
||||
EEPROM_SEM_TIMEOUT);
|
||||
if (ret >= 0) {
|
||||
@ -322,7 +346,8 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
|
||||
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock to be ready */
|
||||
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
25000);
|
||||
if (ret < 0)
|
||||
@ -345,7 +370,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
|
||||
|
||||
_iwl_write32(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
|
||||
ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
@ -538,7 +564,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
||||
_iwl_write32(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
|
||||
|
||||
ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
|
||||
ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
CSR_EEPROM_REG_READ_VALID_MSK,
|
||||
IWL_EEPROM_ACCESS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
|
@ -63,6 +63,8 @@
|
||||
#ifndef __iwl_eeprom_h__
|
||||
#define __iwl_eeprom_h__
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
struct iwl_priv;
|
||||
|
||||
/*
|
||||
@ -256,6 +258,12 @@ struct iwl_eeprom_enhanced_txpwr {
|
||||
#define EEPROM_5050_TX_POWER_VERSION (4)
|
||||
#define EEPROM_5050_EEPROM_VERSION (0x21E)
|
||||
|
||||
/* 1000 Specific */
|
||||
#define EEPROM_1000_EEPROM_VERSION (0x15C)
|
||||
|
||||
/* 60x0 Specific */
|
||||
#define EEPROM_6000_EEPROM_VERSION (0x434)
|
||||
|
||||
/* OTP */
|
||||
/* lower blocks contain EEPROM image and calibration data */
|
||||
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
|
||||
@ -370,12 +378,10 @@ struct iwl_eeprom_calib_info {
|
||||
#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
|
||||
#define EEPROM_VERSION (2*0x44) /* 2 bytes */
|
||||
#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
|
||||
#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
|
||||
#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
|
||||
#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
|
||||
#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */
|
||||
#define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */
|
||||
#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
|
||||
|
||||
/* The following masks are to be applied on EEPROM_RADIO_CONFIG */
|
||||
#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */
|
||||
@ -387,7 +393,12 @@ struct iwl_eeprom_calib_info {
|
||||
|
||||
#define EEPROM_3945_RF_CFG_TYPE_MAX 0x0
|
||||
#define EEPROM_4965_RF_CFG_TYPE_MAX 0x1
|
||||
#define EEPROM_5000_RF_CFG_TYPE_MAX 0x3
|
||||
|
||||
/* Radio Config for 5000 and up */
|
||||
#define EEPROM_RF_CONFIG_TYPE_R3x3 0x0
|
||||
#define EEPROM_RF_CONFIG_TYPE_R2x2 0x1
|
||||
#define EEPROM_RF_CONFIG_TYPE_R1x2 0x2
|
||||
#define EEPROM_RF_CONFIG_TYPE_MAX 0x3
|
||||
|
||||
/*
|
||||
* Per-channel regulatory data.
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-devtrace.h"
|
||||
|
||||
/*
|
||||
* IO, register, and NIC memory access functions
|
||||
@ -61,7 +62,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define _iwl_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs))
|
||||
static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite32(priv, ofs, val);
|
||||
iowrite32(val, priv->hw_base + ofs);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
|
||||
u32 ofs, u32 val)
|
||||
@ -75,7 +81,13 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
|
||||
#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val)
|
||||
#endif
|
||||
|
||||
#define _iwl_read32(priv, ofs) ioread32((priv)->hw_base + (ofs))
|
||||
static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs)
|
||||
{
|
||||
u32 val = ioread32(priv->hw_base + ofs);
|
||||
trace_iwlwifi_dev_ioread32(priv, ofs, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
|
||||
{
|
||||
|
@ -42,15 +42,11 @@
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static const char *led_type_str[] = {
|
||||
__stringify(IWL_LED_TRG_TX),
|
||||
__stringify(IWL_LED_TRG_RX),
|
||||
__stringify(IWL_LED_TRG_ASSOC),
|
||||
__stringify(IWL_LED_TRG_RADIO),
|
||||
NULL
|
||||
};
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
/* default: IWL_LED_BLINK(0) using blinking index table */
|
||||
static int led_mode;
|
||||
module_param(led_mode, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), "
|
||||
"(default 0)\n");
|
||||
|
||||
|
||||
static const struct {
|
||||
@ -65,11 +61,11 @@ static const struct {
|
||||
{70, 65, 65},
|
||||
{50, 75, 75},
|
||||
{20, 85, 85},
|
||||
{15, 95, 95 },
|
||||
{10, 110, 110},
|
||||
{5, 130, 130},
|
||||
{10, 95, 95},
|
||||
{5, 110, 110},
|
||||
{1, 130, 130},
|
||||
{0, 167, 167},
|
||||
/* SOLID_ON */
|
||||
/* SOLID_ON */
|
||||
{-1, IWL_LED_SOLID, 0}
|
||||
};
|
||||
|
||||
@ -78,191 +74,74 @@ static const struct {
|
||||
#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */
|
||||
#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
|
||||
|
||||
/* [0-256] -> [0..8] FIXME: we need [0..10] */
|
||||
static inline int iwl_brightness_to_idx(enum led_brightness brightness)
|
||||
/*
|
||||
* Adjust led blink rate to compensate on a MAC Clock difference on every HW
|
||||
* Led blink rate analysis showed an average deviation of 0% on 3945,
|
||||
* 5% on 4965 HW and 20% on 5000 series and up.
|
||||
* Need to compensate on the led on/off time per HW according to the deviation
|
||||
* to achieve the desired led frequency
|
||||
* The calculation is: (100-averageDeviation)/100 * blinkTime
|
||||
* For code efficiency the calculation will be:
|
||||
* compensation = (100 - averageDeviation) * 64 / 100
|
||||
* NewBlinkTime = (compensation * BlinkTime) / 64
|
||||
*/
|
||||
static inline u8 iwl_blink_compensation(struct iwl_priv *priv,
|
||||
u8 time, u16 compensation)
|
||||
{
|
||||
return fls(0x000000FF & (u32)brightness);
|
||||
}
|
||||
if (!compensation) {
|
||||
IWL_ERR(priv, "undefined blink compensation: "
|
||||
"use pre-defined blinking time\n");
|
||||
return time;
|
||||
}
|
||||
|
||||
/* Send led command */
|
||||
static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_LEDS_CMD,
|
||||
.len = sizeof(struct iwl_led_cmd),
|
||||
.data = led_cmd,
|
||||
.flags = CMD_ASYNC,
|
||||
.callback = NULL,
|
||||
};
|
||||
u32 reg;
|
||||
|
||||
reg = iwl_read32(priv, CSR_LED_REG);
|
||||
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
|
||||
iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
|
||||
|
||||
return iwl_send_cmd(priv, &cmd);
|
||||
return (u8)((time * compensation) >> 6);
|
||||
}
|
||||
|
||||
/* Set led pattern command */
|
||||
static int iwl_led_pattern(struct iwl_priv *priv, int led_id,
|
||||
unsigned int idx)
|
||||
static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx)
|
||||
{
|
||||
struct iwl_led_cmd led_cmd = {
|
||||
.id = led_id,
|
||||
.id = IWL_LED_LINK,
|
||||
.interval = IWL_DEF_LED_INTRVL
|
||||
};
|
||||
|
||||
BUG_ON(idx > IWL_MAX_BLINK_TBL);
|
||||
|
||||
led_cmd.on = blink_tbl[idx].on_time;
|
||||
led_cmd.off = blink_tbl[idx].off_time;
|
||||
IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n",
|
||||
priv->cfg->led_compensation);
|
||||
led_cmd.on =
|
||||
iwl_blink_compensation(priv, blink_tbl[idx].on_time,
|
||||
priv->cfg->led_compensation);
|
||||
led_cmd.off =
|
||||
iwl_blink_compensation(priv, blink_tbl[idx].off_time,
|
||||
priv->cfg->led_compensation);
|
||||
|
||||
return iwl_send_led_cmd(priv, &led_cmd);
|
||||
return priv->cfg->ops->led->cmd(priv, &led_cmd);
|
||||
}
|
||||
|
||||
/* Set led register off */
|
||||
static int iwl_led_on_reg(struct iwl_priv *priv, int led_id)
|
||||
int iwl_led_start(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "led on %d\n", led_id);
|
||||
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
|
||||
return 0;
|
||||
return priv->cfg->ops->led->on(priv);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_led_start);
|
||||
|
||||
#if 0
|
||||
/* Set led on command */
|
||||
static int iwl_led_on(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
struct iwl_led_cmd led_cmd = {
|
||||
.id = led_id,
|
||||
.on = IWL_LED_SOLID,
|
||||
.off = 0,
|
||||
.interval = IWL_DEF_LED_INTRVL
|
||||
};
|
||||
return iwl_send_led_cmd(priv, &led_cmd);
|
||||
}
|
||||
|
||||
/* Set led off command */
|
||||
int iwl_led_off(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
struct iwl_led_cmd led_cmd = {
|
||||
.id = led_id,
|
||||
.on = 0,
|
||||
.off = 0,
|
||||
.interval = IWL_DEF_LED_INTRVL
|
||||
};
|
||||
IWL_DEBUG_LED(priv, "led off %d\n", led_id);
|
||||
return iwl_send_led_cmd(priv, &led_cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Set led register off */
|
||||
static int iwl_led_off_reg(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "LED Reg off\n");
|
||||
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set led register in case of disassociation according to rfkill state
|
||||
*/
|
||||
static int iwl_led_associate(struct iwl_priv *priv, int led_id)
|
||||
int iwl_led_associate(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_LED(priv, "Associated\n");
|
||||
priv->allow_blinking = 1;
|
||||
return iwl_led_on_reg(priv, led_id);
|
||||
if (led_mode == IWL_LED_BLINK)
|
||||
priv->allow_blinking = 1;
|
||||
priv->last_blink_time = jiffies;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int iwl_led_disassociate(struct iwl_priv *priv, int led_id)
|
||||
|
||||
int iwl_led_disassociate(struct iwl_priv *priv)
|
||||
{
|
||||
priv->allow_blinking = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* brightness call back function for Tx/Rx LED
|
||||
*/
|
||||
static int iwl_led_associated(struct iwl_priv *priv, int led_id)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
|
||||
!test_bit(STATUS_READY, &priv->status))
|
||||
return 0;
|
||||
|
||||
|
||||
/* start counting Tx/Rx bytes */
|
||||
if (!priv->last_blink_time && priv->allow_blinking)
|
||||
priv->last_blink_time = jiffies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* brightness call back for association and radio
|
||||
*/
|
||||
static void iwl_led_brightness_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev);
|
||||
struct iwl_priv *priv = led->priv;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
|
||||
IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n",
|
||||
led_type_str[led->type], brightness);
|
||||
switch (brightness) {
|
||||
case LED_FULL:
|
||||
if (led->led_on)
|
||||
led->led_on(priv, IWL_LED_LINK);
|
||||
break;
|
||||
case LED_OFF:
|
||||
if (led->led_off)
|
||||
led->led_off(priv, IWL_LED_LINK);
|
||||
break;
|
||||
default:
|
||||
if (led->led_pattern) {
|
||||
int idx = iwl_brightness_to_idx(brightness);
|
||||
led->led_pattern(priv, IWL_LED_LINK, idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Register led class with the system
|
||||
*/
|
||||
static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led,
|
||||
enum led_type type, u8 set_led,
|
||||
char *trigger)
|
||||
{
|
||||
struct device *device = wiphy_dev(priv->hw->wiphy);
|
||||
int ret;
|
||||
|
||||
led->led_dev.name = led->name;
|
||||
led->led_dev.brightness_set = iwl_led_brightness_set;
|
||||
led->led_dev.default_trigger = trigger;
|
||||
|
||||
led->priv = priv;
|
||||
led->type = type;
|
||||
|
||||
ret = led_classdev_register(device, &led->led_dev);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error: failed to register led handler.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
led->registered = 1;
|
||||
|
||||
if (set_led && led->led_on)
|
||||
led->led_on(priv, IWL_LED_LINK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* calculate blink rate according to last second Tx/Rx activities
|
||||
*/
|
||||
@ -288,7 +167,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv)
|
||||
i = IWL_MAX_BLINK_TBL;
|
||||
else
|
||||
for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
|
||||
if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
|
||||
if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
|
||||
break;
|
||||
|
||||
IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i);
|
||||
@ -317,8 +196,7 @@ void iwl_leds_background(struct iwl_priv *priv)
|
||||
priv->last_blink_time = 0;
|
||||
if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
|
||||
priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
|
||||
iwl_led_pattern(priv, IWL_LED_LINK,
|
||||
IWL_SOLID_BLINK_IDX);
|
||||
iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -331,111 +209,18 @@ void iwl_leds_background(struct iwl_priv *priv)
|
||||
|
||||
/* call only if blink rate change */
|
||||
if (blink_idx != priv->last_blink_rate)
|
||||
iwl_led_pattern(priv, IWL_LED_LINK, blink_idx);
|
||||
iwl_led_pattern(priv, blink_idx);
|
||||
|
||||
priv->last_blink_time = jiffies;
|
||||
priv->last_blink_rate = blink_idx;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_leds_background);
|
||||
|
||||
/* Register all led handler */
|
||||
int iwl_leds_register(struct iwl_priv *priv)
|
||||
void iwl_leds_init(struct iwl_priv *priv)
|
||||
{
|
||||
char *trigger;
|
||||
int ret;
|
||||
|
||||
priv->last_blink_rate = 0;
|
||||
priv->led_tpt = 0;
|
||||
priv->last_blink_time = 0;
|
||||
priv->allow_blinking = 0;
|
||||
|
||||
trigger = ieee80211_get_radio_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_RADIO].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg;
|
||||
priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg;
|
||||
priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
|
||||
|
||||
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO],
|
||||
IWL_LED_TRG_RADIO, 1, trigger);
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
trigger = ieee80211_get_assoc_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_ASSOC].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC],
|
||||
IWL_LED_TRG_ASSOC, 0, trigger);
|
||||
|
||||
/* for assoc always turn led on */
|
||||
priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate;
|
||||
priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate;
|
||||
priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
trigger = ieee80211_get_rx_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_RX].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX],
|
||||
IWL_LED_TRG_RX, 0, trigger);
|
||||
|
||||
priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated;
|
||||
priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated;
|
||||
priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern;
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
trigger = ieee80211_get_tx_led_name(priv->hw);
|
||||
snprintf(priv->led[IWL_LED_TRG_TX].name,
|
||||
sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX",
|
||||
wiphy_name(priv->hw->wiphy));
|
||||
|
||||
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX],
|
||||
IWL_LED_TRG_TX, 0, trigger);
|
||||
|
||||
priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated;
|
||||
priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated;
|
||||
priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern;
|
||||
|
||||
if (ret)
|
||||
goto exit_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_fail:
|
||||
iwl_leds_unregister(priv);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_leds_register);
|
||||
|
||||
/* unregister led class */
|
||||
static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led)
|
||||
{
|
||||
if (!led->registered)
|
||||
return;
|
||||
|
||||
led_classdev_unregister(&led->led_dev);
|
||||
|
||||
if (set_led)
|
||||
led->led_dev.brightness_set(&led->led_dev, LED_OFF);
|
||||
led->registered = 0;
|
||||
}
|
||||
|
||||
/* Unregister all led handlers */
|
||||
void iwl_leds_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
|
||||
iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
|
||||
iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
|
||||
iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_leds_unregister);
|
||||
|
||||
EXPORT_SYMBOL(iwl_leds_init);
|
||||
|
@ -30,9 +30,6 @@
|
||||
|
||||
struct iwl_priv;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
#include <linux/leds.h>
|
||||
|
||||
#define IWL_LED_SOLID 11
|
||||
#define IWL_LED_NAME_LEN 31
|
||||
#define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
|
||||
@ -47,38 +44,23 @@ enum led_type {
|
||||
IWL_LED_TRG_RADIO,
|
||||
IWL_LED_TRG_MAX,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
|
||||
struct iwl_led {
|
||||
struct iwl_priv *priv;
|
||||
struct led_classdev led_dev;
|
||||
char name[32];
|
||||
|
||||
int (*led_on) (struct iwl_priv *priv, int led_id);
|
||||
int (*led_off) (struct iwl_priv *priv, int led_id);
|
||||
int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx);
|
||||
|
||||
enum led_type type;
|
||||
unsigned int registered;
|
||||
/*
|
||||
* LED mode
|
||||
* IWL_LED_BLINK: adjust led blink rate based on blink table
|
||||
* IWL_LED_RF_STATE: turn LED on/off based on RF state
|
||||
* LED ON = RF ON
|
||||
* LED OFF = RF OFF
|
||||
*/
|
||||
enum iwl_led_mode {
|
||||
IWL_LED_BLINK,
|
||||
IWL_LED_RF_STATE,
|
||||
};
|
||||
|
||||
int iwl_leds_register(struct iwl_priv *priv);
|
||||
void iwl_leds_unregister(struct iwl_priv *priv);
|
||||
void iwl_leds_init(struct iwl_priv *priv);
|
||||
void iwl_leds_background(struct iwl_priv *priv);
|
||||
int iwl_led_start(struct iwl_priv *priv);
|
||||
int iwl_led_associate(struct iwl_priv *priv);
|
||||
int iwl_led_disassociate(struct iwl_priv *priv);
|
||||
|
||||
#else
|
||||
static inline int iwl_leds_register(struct iwl_priv *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void iwl_leds_unregister(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
static inline void iwl_leds_background(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IWLWIFI_LEDS */
|
||||
#endif /* __iwl_leds_h__ */
|
||||
|
@ -165,26 +165,26 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
||||
*=============================================================================
|
||||
* Condition Nxt State Condition Nxt State Condition Nxt State
|
||||
*-----------------------------------------------------------------------------
|
||||
* IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
|
||||
* IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
|
||||
* IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
|
||||
* IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
|
||||
* IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
|
||||
* IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
|
||||
* IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
|
||||
*=============================================================================
|
||||
*/
|
||||
static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
|
||||
{IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
|
||||
{IWL_TI_1, 105, CT_KILL_THRESHOLD},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
|
||||
{IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
|
||||
};
|
||||
static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
|
||||
{IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
|
||||
{IWL_TI_2, 110, CT_KILL_THRESHOLD},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
|
||||
{IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
|
||||
};
|
||||
static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
|
||||
{IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
|
||||
{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
|
||||
};
|
||||
static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
|
||||
{IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
|
||||
@ -294,6 +294,9 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
|
||||
|
||||
if (priv->cfg->broken_powersave)
|
||||
iwl_power_sleep_cam_cmd(priv, &cmd);
|
||||
else if (priv->cfg->supports_idle &&
|
||||
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
|
||||
else if (tt->state >= IWL_TI_1)
|
||||
iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
|
||||
else if (!enabled)
|
||||
@ -348,6 +351,23 @@ bool iwl_ht_enabled(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_ht_enabled);
|
||||
|
||||
bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
|
||||
{
|
||||
s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
|
||||
bool within_margin = false;
|
||||
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
|
||||
temp = KELVIN_TO_CELSIUS(priv->temperature);
|
||||
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
|
||||
CT_KILL_THRESHOLD_LEGACY) ? true : false;
|
||||
else
|
||||
within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
|
||||
CT_KILL_THRESHOLD) ? true : false;
|
||||
return within_margin;
|
||||
}
|
||||
|
||||
enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
@ -372,6 +392,7 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
|
||||
#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */
|
||||
|
||||
/*
|
||||
* toggle the bit to wake up uCode and check the temperature
|
||||
@ -409,6 +430,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
|
||||
/* Reschedule the ct_kill timer to occur in
|
||||
* CT_KILL_EXIT_DURATION seconds to ensure we get a
|
||||
* thermal update */
|
||||
IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
|
||||
mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
|
||||
CT_KILL_EXIT_DURATION * HZ);
|
||||
}
|
||||
@ -432,6 +454,33 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_tt_ready_for_ct_kill(unsigned long data)
|
||||
{
|
||||
struct iwl_priv *priv = (struct iwl_priv *)data;
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* temperature timer expired, ready to go into CT_KILL state */
|
||||
if (tt->state != IWL_TI_CT_KILL) {
|
||||
IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n");
|
||||
tt->state = IWL_TI_CT_KILL;
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
|
||||
/* make request to retrieve statistics information */
|
||||
iwl_send_statistics_request(priv, 0);
|
||||
/* Reschedule the ct_kill wait timer */
|
||||
mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
|
||||
jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
|
||||
}
|
||||
|
||||
#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
|
||||
#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
|
||||
#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
|
||||
@ -445,7 +494,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
|
||||
* Throttle early enough to lower the power consumption before
|
||||
* drastic steps are needed
|
||||
*/
|
||||
static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
{
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
enum iwl_tt_state old_state;
|
||||
@ -474,6 +523,8 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
tt->tt_previous_temp = temp;
|
||||
#endif
|
||||
/* stop ct_kill_waiting_tm timer */
|
||||
del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
|
||||
if (tt->state != old_state) {
|
||||
switch (tt->state) {
|
||||
case IWL_TI_0:
|
||||
@ -494,17 +545,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
break;
|
||||
}
|
||||
mutex_lock(&priv->mutex);
|
||||
if (iwl_power_update_mode(priv, true)) {
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
clear_bit(STATUS_CT_KILL, &priv->status);
|
||||
if (tt->state != IWL_TI_CT_KILL &&
|
||||
iwl_power_update_mode(priv, true)) {
|
||||
/* TT state not updated
|
||||
* try again during next temperature read
|
||||
*/
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
tt->state = old_state;
|
||||
IWL_ERR(priv, "Cannot update power mode, "
|
||||
"TT state not updated\n");
|
||||
} else {
|
||||
if (tt->state == IWL_TI_CT_KILL)
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
else if (old_state == IWL_TI_CT_KILL &&
|
||||
if (tt->state == IWL_TI_CT_KILL) {
|
||||
if (force) {
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
} else {
|
||||
iwl_prepare_ct_kill_task(priv);
|
||||
tt->state = old_state;
|
||||
}
|
||||
} else if (old_state == IWL_TI_CT_KILL &&
|
||||
tt->state != IWL_TI_CT_KILL)
|
||||
iwl_perform_ct_kill_task(priv, false);
|
||||
IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
|
||||
@ -531,13 +593,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
*=============================================================================
|
||||
* Condition Nxt State Condition Nxt State Condition Nxt State
|
||||
*-----------------------------------------------------------------------------
|
||||
* IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
|
||||
* IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
|
||||
* IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
|
||||
* IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
|
||||
* IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
|
||||
* IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
|
||||
* IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
|
||||
*=============================================================================
|
||||
*/
|
||||
static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
{
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
int i;
|
||||
@ -582,6 +644,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* stop ct_kill_waiting_tm timer */
|
||||
del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
|
||||
if (changed) {
|
||||
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
|
||||
|
||||
@ -613,12 +677,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
}
|
||||
mutex_lock(&priv->mutex);
|
||||
if (iwl_power_update_mode(priv, true)) {
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
clear_bit(STATUS_CT_KILL, &priv->status);
|
||||
if (tt->state != IWL_TI_CT_KILL &&
|
||||
iwl_power_update_mode(priv, true)) {
|
||||
/* TT state not updated
|
||||
* try again during next temperature read
|
||||
*/
|
||||
IWL_ERR(priv, "Cannot update power mode, "
|
||||
"TT state not updated\n");
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
tt->state = old_state;
|
||||
} else {
|
||||
IWL_DEBUG_POWER(priv,
|
||||
@ -626,9 +695,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
|
||||
tt->state);
|
||||
if (old_state != IWL_TI_CT_KILL &&
|
||||
tt->state == IWL_TI_CT_KILL) {
|
||||
IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n");
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
|
||||
if (force) {
|
||||
IWL_DEBUG_POWER(priv,
|
||||
"Enter IWL_TI_CT_KILL\n");
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
} else {
|
||||
iwl_prepare_ct_kill_task(priv);
|
||||
tt->state = old_state;
|
||||
}
|
||||
} else if (old_state == IWL_TI_CT_KILL &&
|
||||
tt->state != IWL_TI_CT_KILL) {
|
||||
IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
|
||||
@ -665,10 +740,11 @@ static void iwl_bg_ct_enter(struct work_struct *work)
|
||||
"- ucode going to sleep!\n");
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
iwl_legacy_tt_handler(priv,
|
||||
IWL_MINIMAL_POWER_THRESHOLD);
|
||||
IWL_MINIMAL_POWER_THRESHOLD,
|
||||
true);
|
||||
else
|
||||
iwl_advance_tt_handler(priv,
|
||||
CT_KILL_THRESHOLD + 1);
|
||||
CT_KILL_THRESHOLD + 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,11 +771,18 @@ static void iwl_bg_ct_exit(struct work_struct *work)
|
||||
IWL_ERR(priv,
|
||||
"Device temperature below critical"
|
||||
"- ucode awake!\n");
|
||||
/*
|
||||
* exit from CT_KILL state
|
||||
* reset the current temperature reading
|
||||
*/
|
||||
priv->temperature = 0;
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
iwl_legacy_tt_handler(priv,
|
||||
IWL_REDUCED_PERFORMANCE_THRESHOLD_2);
|
||||
IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
|
||||
true);
|
||||
else
|
||||
iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD);
|
||||
iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,9 +818,9 @@ static void iwl_bg_tt_work(struct work_struct *work)
|
||||
temp = KELVIN_TO_CELSIUS(priv->temperature);
|
||||
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
iwl_legacy_tt_handler(priv, temp);
|
||||
iwl_legacy_tt_handler(priv, temp, false);
|
||||
else
|
||||
iwl_advance_tt_handler(priv, temp);
|
||||
iwl_advance_tt_handler(priv, temp, false);
|
||||
}
|
||||
|
||||
void iwl_tt_handler(struct iwl_priv *priv)
|
||||
@ -768,8 +851,12 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
||||
tt->state = IWL_TI_0;
|
||||
init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
|
||||
priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
|
||||
priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
|
||||
|
||||
priv->thermal_throttle.ct_kill_exit_tm.function =
|
||||
iwl_tt_check_exit_ct_kill;
|
||||
init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
|
||||
priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv;
|
||||
priv->thermal_throttle.ct_kill_waiting_tm.function =
|
||||
iwl_tt_ready_for_ct_kill;
|
||||
/* setup deferred ct kill work */
|
||||
INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
|
||||
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
|
||||
@ -826,6 +913,8 @@ void iwl_tt_exit(struct iwl_priv *priv)
|
||||
|
||||
/* stop ct_kill_exit_tm timer if activated */
|
||||
del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
|
||||
/* stop ct_kill_waiting_tm timer if activated */
|
||||
del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
|
||||
cancel_work_sync(&priv->tt_work);
|
||||
cancel_work_sync(&priv->ct_enter);
|
||||
cancel_work_sync(&priv->ct_exit);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define IWL_ABSOLUTE_ZERO 0
|
||||
#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
|
||||
#define IWL_TT_INCREASE_MARGIN 5
|
||||
#define IWL_TT_CT_KILL_MARGIN 3
|
||||
|
||||
enum iwl_antenna_ok {
|
||||
IWL_ANT_OK_NONE,
|
||||
@ -110,6 +111,7 @@ struct iwl_tt_mgmt {
|
||||
struct iwl_tt_restriction *restriction;
|
||||
struct iwl_tt_trans *transaction;
|
||||
struct timer_list ct_kill_exit_tm;
|
||||
struct timer_list ct_kill_waiting_tm;
|
||||
};
|
||||
|
||||
enum iwl_power_level {
|
||||
@ -129,6 +131,7 @@ struct iwl_power_mgr {
|
||||
|
||||
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
|
||||
bool iwl_ht_enabled(struct iwl_priv *priv);
|
||||
bool iwl_within_ct_kill_margin(struct iwl_priv *priv);
|
||||
enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
|
||||
enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
|
||||
void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
|
||||
|
@ -27,7 +27,6 @@
|
||||
*****************************************************************************/
|
||||
#include <linux/types.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/lib80211.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
|
@ -709,7 +709,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
dma_addr_t phys_addr;
|
||||
dma_addr_t txcmd_phys;
|
||||
dma_addr_t scratch_phys;
|
||||
u16 len, len_org;
|
||||
u16 len, len_org, firstlen, secondlen;
|
||||
u16 seq_number = 0;
|
||||
__le16 fc;
|
||||
u8 hdr_len;
|
||||
@ -842,7 +842,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
sizeof(struct iwl_cmd_header) + hdr_len;
|
||||
|
||||
len_org = len;
|
||||
len = (len + 3) & ~3;
|
||||
firstlen = len = (len + 3) & ~3;
|
||||
|
||||
if (len_org != len)
|
||||
len_org = 1;
|
||||
@ -876,7 +876,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
|
||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||
* if any (802.11 null frames have no payload). */
|
||||
len = skb->len - hdr_len;
|
||||
secondlen = len = skb->len - hdr_len;
|
||||
if (len) {
|
||||
phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
|
||||
len, PCI_DMA_TODEVICE);
|
||||
@ -910,6 +910,12 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
|
||||
len, PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
trace_iwlwifi_dev_tx(priv,
|
||||
&((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
|
||||
sizeof(struct iwl_tfd),
|
||||
&out_cmd->hdr, firstlen,
|
||||
skb->data + hdr_len, secondlen);
|
||||
|
||||
/* Tell device the write index *just past* this latest filled TFD */
|
||||
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||
ret = iwl_txq_update_write_ptr(priv, txq);
|
||||
@ -969,13 +975,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
|
||||
!(cmd->flags & CMD_SIZE_HUGE));
|
||||
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n");
|
||||
if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
|
||||
IWL_DEBUG_INFO(priv, "Not sending command - RF/CT KILL\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
|
||||
IWL_ERR(priv, "No space for Tx\n");
|
||||
if (iwl_within_ct_kill_margin(priv))
|
||||
iwl_tt_enter_ct_kill(priv);
|
||||
else {
|
||||
IWL_ERR(priv, "Restarting adapter due to queue full\n");
|
||||
queue_work(priv->workqueue, &priv->restart);
|
||||
}
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
@ -1038,6 +1050,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
pci_unmap_addr_set(out_meta, mapping, phys_addr);
|
||||
pci_unmap_len_set(out_meta, len, fix_size);
|
||||
|
||||
trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags);
|
||||
|
||||
priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
|
||||
phys_addr, fix_size, 1,
|
||||
U32_PAD(cmd->len));
|
||||
@ -1400,7 +1414,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
||||
|
||||
info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->flags = IEEE80211_TX_STAT_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
info->status.ampdu_ack_map = successes;
|
||||
info->status.ampdu_ack_len = agg->frame_count;
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
#include <net/lib80211.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
@ -456,9 +455,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
|
||||
tx->timeout.pm_frame_timeout = cpu_to_le16(2);
|
||||
} else {
|
||||
tx->timeout.pm_frame_timeout = 0;
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
|
||||
#endif
|
||||
}
|
||||
|
||||
tx->driver_txop = 0;
|
||||
@ -1405,6 +1401,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
|
||||
trace_iwlwifi_dev_rx(priv, pkt,
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
||||
/* Reclaim a command buffer only if this packet is a response
|
||||
* to a (driver-originated) command.
|
||||
* If the packet (e.g. Rx frame) originated from uCode,
|
||||
@ -1550,8 +1549,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
|
||||
"%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
|
||||
desc_lookup(desc), desc, time, blink1, blink2,
|
||||
ilink1, ilink2, data1);
|
||||
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,
|
||||
0, blink1, blink2, ilink1, ilink2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define EVENT_START_OFFSET (6 * sizeof(u32))
|
||||
@ -1591,10 +1591,12 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
if (mode == 0) {
|
||||
/* data, ev */
|
||||
IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
|
||||
} else {
|
||||
data = iwl_read_targ_mem(priv, ptr);
|
||||
ptr += sizeof(u32);
|
||||
IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2478,7 +2480,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
||||
|
||||
iwl3945_reg_txpower_periodic(priv);
|
||||
|
||||
iwl3945_led_register(priv);
|
||||
iwl_leds_init(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
|
||||
set_bit(STATUS_READY, &priv->status);
|
||||
@ -2516,7 +2518,6 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
||||
if (!exit_pending)
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
iwl3945_led_unregister(priv);
|
||||
iwl_clear_stations_table(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
@ -3151,6 +3152,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
|
||||
* no need to poll the killswitch state anymore */
|
||||
cancel_delayed_work(&priv->rfkill_poll);
|
||||
|
||||
iwl_led_start(priv);
|
||||
|
||||
priv->is_open = 1;
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
return 0;
|
||||
@ -4225,18 +4228,19 @@ static void __exit iwl3945_exit(void)
|
||||
|
||||
MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
|
||||
|
||||
module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
|
||||
module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
|
||||
module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
|
||||
module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(swcrypto,
|
||||
"using software crypto (default 1 [software])\n");
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
module_param_named(debug, iwl_debug_level, uint, 0644);
|
||||
module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "debug output mask");
|
||||
#endif
|
||||
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444);
|
||||
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
|
||||
int, S_IRUGO);
|
||||
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
|
||||
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444);
|
||||
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
|
||||
|
||||
module_exit(iwl3945_exit);
|
||||
|
@ -637,6 +637,8 @@ static int __iwm_up(struct iwm_priv *iwm)
|
||||
IWM_ERR(iwm, "MAC reading failed\n");
|
||||
goto err_disable;
|
||||
}
|
||||
memcpy(iwm_to_ndev(iwm)->perm_addr, iwm_to_ndev(iwm)->dev_addr,
|
||||
ETH_ALEN);
|
||||
|
||||
/* We can load the FWs */
|
||||
ret = iwm_load_fw(iwm);
|
||||
|
39
drivers/net/wireless/libertas/Kconfig
Normal file
39
drivers/net/wireless/libertas/Kconfig
Normal file
@ -0,0 +1,39 @@
|
||||
config LIBERTAS
|
||||
tristate "Marvell 8xxx Libertas WLAN driver support"
|
||||
depends on WLAN_80211 && CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select LIB80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A library for Marvell Libertas 8xxx devices.
|
||||
|
||||
config LIBERTAS_USB
|
||||
tristate "Marvell Libertas 8388 USB 802.11b/g cards"
|
||||
depends on LIBERTAS && USB
|
||||
---help---
|
||||
A driver for Marvell Libertas 8388 USB devices.
|
||||
|
||||
config LIBERTAS_CS
|
||||
tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
|
||||
depends on LIBERTAS && PCMCIA
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385 CompactFlash devices.
|
||||
|
||||
config LIBERTAS_SDIO
|
||||
tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
|
||||
depends on LIBERTAS && MMC
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
|
||||
|
||||
config LIBERTAS_SPI
|
||||
tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
|
||||
depends on LIBERTAS && SPI
|
||||
---help---
|
||||
A driver for Marvell Libertas 8686 SPI devices.
|
||||
|
||||
config LIBERTAS_DEBUG
|
||||
bool "Enable full debugging output in the Libertas module."
|
||||
depends on LIBERTAS
|
||||
---help---
|
||||
Debugging support.
|
@ -1,5 +1,16 @@
|
||||
libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \
|
||||
debugfs.o persistcfg.o ethtool.o assoc.o
|
||||
libertas-y += 11d.o
|
||||
libertas-y += assoc.o
|
||||
libertas-y += cfg.o
|
||||
libertas-y += cmd.o
|
||||
libertas-y += cmdresp.o
|
||||
libertas-y += debugfs.o
|
||||
libertas-y += ethtool.o
|
||||
libertas-y += main.o
|
||||
libertas-y += persistcfg.o
|
||||
libertas-y += rx.o
|
||||
libertas-y += scan.o
|
||||
libertas-y += tx.o
|
||||
libertas-y += wext.o
|
||||
|
||||
usb8xxx-objs += if_usb.o
|
||||
libertas_cs-objs += if_cs.o
|
||||
|
@ -1,5 +1,5 @@
|
||||
================================================================================
|
||||
README for USB8388
|
||||
README for Libertas
|
||||
|
||||
(c) Copyright © 2003-2006, Marvell International Ltd.
|
||||
All Rights Reserved
|
||||
@ -226,4 +226,28 @@ setuserscan
|
||||
All entries in the scan table (not just the new scan data when keep=1)
|
||||
will be displayed upon completion by use of the getscantable ioctl.
|
||||
|
||||
========================
|
||||
IWCONFIG COMMANDS
|
||||
========================
|
||||
power period
|
||||
|
||||
This command is used to configure the station in deep sleep mode /
|
||||
auto deep sleep mode.
|
||||
|
||||
The timer is implemented to monitor the activities (command, event,
|
||||
etc.). When an activity is detected station will exit from deep
|
||||
sleep mode automatically and restart the timer. At timer expiry
|
||||
(no activity for defined time period) the deep sleep mode is entered
|
||||
automatically.
|
||||
|
||||
Note: this command is for SDIO interface only.
|
||||
|
||||
Usage:
|
||||
To enable deep sleep mode do:
|
||||
iwconfig wlan0 power period 0
|
||||
To enable auto deep sleep mode with idle time period 5 seconds do:
|
||||
iwconfig wlan0 power period 5
|
||||
To disable deep sleep/auto deep sleep mode do:
|
||||
iwconfig wlan0 power period -1
|
||||
|
||||
==============================================================================
|
||||
|
198
drivers/net/wireless/libertas/cfg.c
Normal file
198
drivers/net/wireless/libertas/cfg.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Implement cfg80211 ("iw") support.
|
||||
*
|
||||
* Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany
|
||||
* Holger Schurig <hs4233@mail.mn-solutions.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include "cfg.h"
|
||||
#include "cmd.h"
|
||||
|
||||
|
||||
#define CHAN2G(_channel, _freq, _flags) { \
|
||||
.band = IEEE80211_BAND_2GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_channel), \
|
||||
.flags = (_flags), \
|
||||
.max_antenna_gain = 0, \
|
||||
.max_power = 30, \
|
||||
}
|
||||
|
||||
static struct ieee80211_channel lbs_2ghz_channels[] = {
|
||||
CHAN2G(1, 2412, 0),
|
||||
CHAN2G(2, 2417, 0),
|
||||
CHAN2G(3, 2422, 0),
|
||||
CHAN2G(4, 2427, 0),
|
||||
CHAN2G(5, 2432, 0),
|
||||
CHAN2G(6, 2437, 0),
|
||||
CHAN2G(7, 2442, 0),
|
||||
CHAN2G(8, 2447, 0),
|
||||
CHAN2G(9, 2452, 0),
|
||||
CHAN2G(10, 2457, 0),
|
||||
CHAN2G(11, 2462, 0),
|
||||
CHAN2G(12, 2467, 0),
|
||||
CHAN2G(13, 2472, 0),
|
||||
CHAN2G(14, 2484, 0),
|
||||
};
|
||||
|
||||
#define RATETAB_ENT(_rate, _rateid, _flags) { \
|
||||
.bitrate = (_rate), \
|
||||
.hw_value = (_rateid), \
|
||||
.flags = (_flags), \
|
||||
}
|
||||
|
||||
|
||||
static struct ieee80211_rate lbs_rates[] = {
|
||||
RATETAB_ENT(10, 0x1, 0),
|
||||
RATETAB_ENT(20, 0x2, 0),
|
||||
RATETAB_ENT(55, 0x4, 0),
|
||||
RATETAB_ENT(110, 0x8, 0),
|
||||
RATETAB_ENT(60, 0x10, 0),
|
||||
RATETAB_ENT(90, 0x20, 0),
|
||||
RATETAB_ENT(120, 0x40, 0),
|
||||
RATETAB_ENT(180, 0x80, 0),
|
||||
RATETAB_ENT(240, 0x100, 0),
|
||||
RATETAB_ENT(360, 0x200, 0),
|
||||
RATETAB_ENT(480, 0x400, 0),
|
||||
RATETAB_ENT(540, 0x800, 0),
|
||||
};
|
||||
|
||||
static struct ieee80211_supported_band lbs_band_2ghz = {
|
||||
.channels = lbs_2ghz_channels,
|
||||
.n_channels = ARRAY_SIZE(lbs_2ghz_channels),
|
||||
.bitrates = lbs_rates,
|
||||
.n_bitrates = ARRAY_SIZE(lbs_rates),
|
||||
};
|
||||
|
||||
|
||||
static const u32 cipher_suites[] = {
|
||||
WLAN_CIPHER_SUITE_WEP40,
|
||||
WLAN_CIPHER_SUITE_WEP104,
|
||||
WLAN_CIPHER_SUITE_TKIP,
|
||||
WLAN_CIPHER_SUITE_CCMP,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int lbs_cfg_set_channel(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||
int ret = -ENOTSUPP;
|
||||
|
||||
lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type);
|
||||
|
||||
if (channel_type != NL80211_CHAN_NO_HT)
|
||||
goto out;
|
||||
|
||||
ret = lbs_set_channel(priv, chan->hw_value);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static struct cfg80211_ops lbs_cfg80211_ops = {
|
||||
.set_channel = lbs_cfg_set_channel,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* At this time lbs_private *priv doesn't even exist, so we just allocate
|
||||
* memory and don't initialize the wiphy further. This is postponed until we
|
||||
* can talk to the firmware and happens at registration time in
|
||||
* lbs_cfg_wiphy_register().
|
||||
*/
|
||||
struct wireless_dev *lbs_cfg_alloc(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||
|
||||
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
|
||||
if (!wdev) {
|
||||
dev_err(dev, "cannot allocate wireless device\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
wdev->wiphy = wiphy_new(&lbs_cfg80211_ops, sizeof(struct lbs_private));
|
||||
if (!wdev->wiphy) {
|
||||
dev_err(dev, "cannot allocate wiphy\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_wiphy_new;
|
||||
}
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CFG80211);
|
||||
return wdev;
|
||||
|
||||
err_wiphy_new:
|
||||
kfree(wdev);
|
||||
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function get's called after lbs_setup_firmware() determined the
|
||||
* firmware capabities. So we can setup the wiphy according to our
|
||||
* hardware/firmware.
|
||||
*/
|
||||
int lbs_cfg_register(struct lbs_private *priv)
|
||||
{
|
||||
struct wireless_dev *wdev = priv->wdev;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||
|
||||
wdev->wiphy->max_scan_ssids = 1;
|
||||
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
|
||||
/* TODO: BIT(NL80211_IFTYPE_ADHOC); */
|
||||
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
|
||||
/* TODO: honor priv->regioncode */
|
||||
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
|
||||
|
||||
/*
|
||||
* We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have
|
||||
* never seen a firmware without WPA
|
||||
*/
|
||||
wdev->wiphy->cipher_suites = cipher_suites;
|
||||
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
|
||||
|
||||
ret = wiphy_register(wdev->wiphy);
|
||||
if (ret < 0)
|
||||
lbs_pr_err("cannot register wiphy device\n");
|
||||
|
||||
ret = register_netdev(priv->dev);
|
||||
if (ret)
|
||||
lbs_pr_err("cannot register network device\n");
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void lbs_cfg_free(struct lbs_private *priv)
|
||||
{
|
||||
struct wireless_dev *wdev = priv->wdev;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||
|
||||
if (!wdev)
|
||||
return;
|
||||
|
||||
if (wdev->wiphy) {
|
||||
wiphy_unregister(wdev->wiphy);
|
||||
wiphy_free(wdev->wiphy);
|
||||
}
|
||||
kfree(wdev);
|
||||
}
|
16
drivers/net/wireless/libertas/cfg.h
Normal file
16
drivers/net/wireless/libertas/cfg.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __LBS_CFG80211_H__
|
||||
#define __LBS_CFG80211_H__
|
||||
|
||||
#include "dev.h"
|
||||
|
||||
struct wireless_dev *lbs_cfg_alloc(struct device *dev);
|
||||
int lbs_cfg_register(struct lbs_private *priv);
|
||||
void lbs_cfg_free(struct lbs_private *priv);
|
||||
|
||||
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
|
||||
u8 ssid_len);
|
||||
int lbs_scan_networks(struct lbs_private *priv, int full_scan);
|
||||
void lbs_cfg_scan_worker(struct work_struct *work);
|
||||
|
||||
|
||||
#endif
|
@ -17,7 +17,6 @@
|
||||
|
||||
static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Simple callback that copies response back into command
|
||||
*
|
||||
@ -75,6 +74,30 @@ static u8 is_command_allowed_in_ps(u16 cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function checks if the command is allowed.
|
||||
*
|
||||
* @param priv A pointer to lbs_private structure
|
||||
* @return allowed or not allowed.
|
||||
*/
|
||||
|
||||
static int lbs_is_cmd_allowed(struct lbs_private *priv)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (!priv->is_auto_deep_sleep_enabled) {
|
||||
if (priv->is_deep_sleep) {
|
||||
lbs_deb_cmd("command not allowed in deep sleep\n");
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the hardware details like MAC address and regulatory region
|
||||
*
|
||||
@ -319,6 +342,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_wait_for_ds_awake(struct lbs_private *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (priv->is_deep_sleep) {
|
||||
if (!wait_event_interruptible_timeout(priv->ds_awake_q,
|
||||
!priv->is_deep_sleep, (10 * HZ))) {
|
||||
lbs_pr_err("ds_awake_q: timer expired\n");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (deep_sleep) {
|
||||
if (priv->is_deep_sleep != 1) {
|
||||
lbs_deb_cmd("deep sleep: sleep\n");
|
||||
BUG_ON(!priv->enter_deep_sleep);
|
||||
ret = priv->enter_deep_sleep(priv);
|
||||
if (!ret) {
|
||||
netif_stop_queue(priv->dev);
|
||||
netif_carrier_off(priv->dev);
|
||||
}
|
||||
} else {
|
||||
lbs_pr_err("deep sleep: already enabled\n");
|
||||
}
|
||||
} else {
|
||||
if (priv->is_deep_sleep) {
|
||||
lbs_deb_cmd("deep sleep: wakeup\n");
|
||||
BUG_ON(!priv->exit_deep_sleep);
|
||||
ret = priv->exit_deep_sleep(priv);
|
||||
if (!ret) {
|
||||
ret = lbs_wait_for_ds_awake(priv);
|
||||
if (ret)
|
||||
lbs_pr_err("deep sleep: wakeup"
|
||||
"failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc)
|
||||
{
|
||||
@ -1242,8 +1319,17 @@ static void lbs_submit_command(struct lbs_private *priv,
|
||||
timeo = HZ/4;
|
||||
}
|
||||
|
||||
/* Setup the timer after transmit command */
|
||||
mod_timer(&priv->command_timer, jiffies + timeo);
|
||||
if (command == CMD_802_11_DEEP_SLEEP) {
|
||||
if (priv->is_auto_deep_sleep_enabled) {
|
||||
priv->wakeup_dev_required = 1;
|
||||
priv->dnld_sent = 0;
|
||||
}
|
||||
priv->is_deep_sleep = 1;
|
||||
lbs_complete_command(priv, cmdnode, 0);
|
||||
} else {
|
||||
/* Setup the timer after transmit command */
|
||||
mod_timer(&priv->command_timer, jiffies + timeo);
|
||||
}
|
||||
|
||||
lbs_deb_leave(LBS_DEB_HOST);
|
||||
}
|
||||
@ -1390,6 +1476,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!lbs_is_cmd_allowed(priv)) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmdnode = lbs_get_cmd_ctrl_node(priv);
|
||||
|
||||
if (cmdnode == NULL) {
|
||||
@ -1505,6 +1596,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
case CMD_802_11_BEACON_CTRL:
|
||||
ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
|
||||
break;
|
||||
case CMD_802_11_DEEP_SLEEP:
|
||||
cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
|
||||
cmdptr->size = cpu_to_le16(S_DS_GEN);
|
||||
break;
|
||||
default:
|
||||
lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
|
||||
ret = -1;
|
||||
@ -2038,6 +2133,11 @@ static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!lbs_is_cmd_allowed(priv)) {
|
||||
cmdnode = ERR_PTR(-EBUSY);
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmdnode = lbs_get_cmd_ctrl_node(priv);
|
||||
if (cmdnode == NULL) {
|
||||
lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user