diff options
Diffstat (limited to 'drivers/net/wireless/ath')
61 files changed, 4060 insertions, 2844 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 11ded15..4e7a7fd 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -1,6 +1,5 @@ menuconfig ATH_COMMON tristate "Atheros Wireless Cards" - depends on WLAN_80211 depends on CFG80211 ---help--- This will enable the support for the Atheros wireless drivers. @@ -16,7 +15,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 diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 4bb0132..8113a50 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -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 diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig index 05918f1..d7a4799 100644 --- a/drivers/net/wireless/ath/ar9170/Kconfig +++ b/drivers/net/wireless/ath/ar9170/Kconfig @@ -1,6 +1,6 @@ config AR9170_USB tristate "Atheros AR9170 802.11n USB support" - depends on USB && MAC80211 && WLAN_80211 + depends on USB && MAC80211 select FW_LOADER help This is a driver for the Atheros "otus" 802.11n USB devices. diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 914e471..9f94598 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -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]; @@ -231,7 +231,7 @@ struct ar9170 { struct sk_buff_head tx_status_ampdu; spinlock_t tx_ampdu_list_lock; struct list_head tx_ampdu_list; - unsigned int tx_ampdu_pending; + atomic_t tx_ampdu_pending; /* rxstream mpdu merge */ struct ar9170_rxstream_mpdu_merge rx_mpdu; diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c index f57a620..cf6f5c4 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ b/drivers/net/wireless/ath/ar9170/cmd.c @@ -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; diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h index a4f0e50..826c45e 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ b/drivers/net/wireless/ath/ar9170/cmd.h @@ -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); /* diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 6cbfb2f..701ddb7 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -152,14 +152,14 @@ enum ar9170_cmd { #define AR9170_MAC_REG_FTF_BIT14 BIT(14) #define AR9170_MAC_REG_FTF_BIT15 BIT(15) #define AR9170_MAC_REG_FTF_BAR BIT(24) -#define AR9170_MAC_REG_FTF_BIT25 BIT(25) +#define AR9170_MAC_REG_FTF_BA BIT(25) #define AR9170_MAC_REG_FTF_PSPOLL BIT(26) #define AR9170_MAC_REG_FTF_RTS BIT(27) #define AR9170_MAC_REG_FTF_CTS BIT(28) #define AR9170_MAC_REG_FTF_ACK BIT(29) #define AR9170_MAC_REG_FTF_CFE BIT(30) #define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) -#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff +#define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff #define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) @@ -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; diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index 614e321..ddc8c09 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -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: diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c1f8c69..7e59b82 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -414,9 +414,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) skb_queue_tail(&ar->tx_status_ampdu, skb); ar9170_tx_fake_ampdu_status(ar); - ar->tx_ampdu_pending--; - if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) + if (atomic_dec_and_test(&ar->tx_ampdu_pending) && + !list_empty(&ar->tx_ampdu_list)) ar9170_tx_ampdu(ar); } @@ -1248,6 +1248,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw) ar->global_ampdu_density = 6; ar->global_ampdu_factor = 3; + atomic_set(&ar->tx_ampdu_pending, 0); ar->bad_hw_nagger = jiffies; err = ar->open(ar); @@ -1773,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar) msecs_to_jiffies(AR9170_TX_TIMEOUT); if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) - ar->tx_ampdu_pending++; + atomic_inc(&ar->tx_ampdu_pending); #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: send frame q:%d =>\n", @@ -1784,7 +1785,7 @@ static void ar9170_tx(struct ar9170 *ar) err = ar->tx(ar, skb); if (unlikely(err)) { if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) - ar->tx_ampdu_pending--; + atomic_dec(&ar->tx_ampdu_pending); frames_failed++; dev_kfree_skb_any(skb); @@ -1931,7 +1932,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_AMPDU) { bool run = ar9170_tx_ampdu_queue(ar, skb); - if (run || !ar->tx_ampdu_pending) + if (run || !atomic_read(&ar->tx_ampdu_pending)) ar9170_tx_ampdu(ar); } else { unsigned int queue = skb_get_queue_mapping(skb); @@ -1952,6 +1953,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 +1964,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 +2133,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 +2193,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, diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index dbd488d..45a415e 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -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); diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e58..6bdcdf6 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -108,15 +108,15 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) return ; spin_lock_irqsave(&aru->tx_urb_lock, flags); - if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { + if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { spin_unlock_irqrestore(&aru->tx_urb_lock, flags); return ; } - aru->tx_submitted_urbs++; + atomic_inc(&aru->tx_submitted_urbs); urb = usb_get_from_anchor(&aru->tx_pending); if (!urb) { - aru->tx_submitted_urbs--; + atomic_dec(&aru->tx_submitted_urbs); spin_unlock_irqrestore(&aru->tx_urb_lock, flags); return ; @@ -133,7 +133,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) err); usb_unanchor_urb(urb); - aru->tx_submitted_urbs--; + atomic_dec(&aru->tx_submitted_urbs); ar9170_tx_callback(&aru->common, urb->context); } @@ -151,7 +151,7 @@ static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) return ; } - aru->tx_submitted_urbs--; + atomic_dec(&aru->tx_submitted_urbs); ar9170_tx_callback(&aru->common, skb); @@ -794,7 +794,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, spin_lock_init(&aru->tx_urb_lock); aru->tx_pending_urbs = 0; - aru->tx_submitted_urbs = 0; + atomic_set(&aru->tx_submitted_urbs, 0); aru->common.stop = ar9170_usb_stop; aru->common.flush = ar9170_usb_flush; diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index d098f4d..a2ce3b1 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -67,7 +67,7 @@ struct ar9170_usb { bool req_one_stage_fw; spinlock_t tx_urb_lock; - unsigned int tx_submitted_urbs; + atomic_t tx_submitted_urbs; unsigned int tx_pending_urbs; struct completion cmd_wait; diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index a63e90c..5e19a73 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -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 */ diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index 06d0066..eb83b7b 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,6 +1,6 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 + depends on PCI && MAC80211 select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6cd5efc..6a2a967 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.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 @@ -204,6 +198,7 @@ #define AR5K_TUNE_CWMAX_11B 1023 #define AR5K_TUNE_CWMAX_XR 7 #define AR5K_TUNE_NOISE_FLOOR -72 +#define AR5K_TUNE_CCA_MAX_GOOD_VALUE -95 #define AR5K_TUNE_MAX_TXPOWER 63 #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false @@ -1012,6 +1007,14 @@ struct ath5k_capabilities { } cap_queues; }; +/* size of noise floor history (keep it a power of two) */ +#define ATH5K_NF_CAL_HIST_MAX 8 +struct ath5k_nfcal_hist +{ + s16 index; /* current index into nfval */ + s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ +}; + /***************************************\ HARDWARE ABSTRACTION LAYER STRUCTURE @@ -1027,6 +1030,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 +1071,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; @@ -1125,6 +1121,8 @@ struct ath5k_hw { struct ieee80211_channel r_last_channel; } ah_radar; + struct ath5k_nfcal_hist ah_nfcal_hist; + /* noise floor from last periodic calibration */ s32 ah_noise_floor; @@ -1160,7 +1158,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 +1201,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); @@ -1288,8 +1285,10 @@ extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); /* PHY calibration */ +void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); +extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); /* Spur mitigation */ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, @@ -1329,17 +1328,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); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 71a1bd25..4228444 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -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,20 +325,21 @@ 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); + ath5k_hw_init_nfcal_hist(ah); + /* 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 +359,4 @@ void ath5k_hw_detach(struct ath5k_hw *ah) ath5k_eeprom_detach(ah); /* assume interrupts are down */ - kfree(ah); } diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95a8e23..cb3dc89 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -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; @@ -1152,19 +1173,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; } @@ -1605,13 +1627,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; @@ -1684,13 +1707,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 @@ -3176,6 +3200,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); @@ -3184,10 +3209,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(); } @@ -3200,6 +3224,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) { diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index a28c42f..b14ba07 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -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 diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 18eb519..8fa4393 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -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 }, diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index b548c8e..d495890 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -59,6 +59,8 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, + /* Acer Aspire One AO531h AO751h (keng-yu.lin@canonical.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) }, /* Acer Ferrari 5000 (russ.dill@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, /* E-machines E510 (tuliom@gmail.com) */ diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 2942f13..64fc1eb 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -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); - - if (assoc_id == 0) { + 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 (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)); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2..8959907 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1124,77 +1124,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah) ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); } +} +static int sign_extend(int val, const int nbits) +{ + int order = BIT(nbits-1); + return (val ^ order) - order; } -/** - * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration - * - * @ah: struct ath5k_hw pointer we are operating on - * @freq: the channel frequency, just used for error logging - * - * This function performs a noise floor calibration of the PHY and waits for - * it to complete. Then the noise floor value is compared to some maximum - * noise floor we consider valid. - * - * Note that this is different from what the madwifi HAL does: it reads the - * noise floor and afterwards initiates the calibration. Since the noise floor - * calibration can take some time to finish, depending on the current channel - * use, that avoids the occasional timeout warnings we are seeing now. - * - * See the following link for an Atheros patent on noise floor calibration: - * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ - * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 +static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) +{ + s32 val; + + val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); + return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); +} + +void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) +{ + int i; + + ah->ah_nfcal_hist.index = 0; + for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) + ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE; +} + +static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) +{ + struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; + hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1); + hist->nfval[hist->index] = noise_floor; +} + +static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) +{ + s16 sort[ATH5K_NF_CAL_HIST_MAX]; + s16 tmp; + int i, j; + + memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort)); + for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) { + for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) { + if (sort[j] > sort[j-1]) { + tmp = sort[j]; + sort[j] = sort[j-1]; + sort[j-1] = tmp; + } + } + } + for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "cal %d:%d\n", i, sort[i]); + } + return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2]; +} + +/* + * When we tell the hardware to perform a noise floor calibration + * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically + * sample-and-hold the minimum noise level seen at the antennas. + * This value is then stored in a ring buffer of recently measured + * noise floor values so we have a moving window of the last few + * samples. * - * XXX: Since during noise floor calibration antennas are detached according to - * the patent, we should stop tx queues here. + * The median of the values in the history is then loaded into the + * hardware for its own use for RSSI and CCA measurements. */ -int -ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) +void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) { - int ret; - unsigned int i; - s32 noise_floor; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 val; + s16 nf, threshold; + u8 ee_mode; - /* - * Enable noise floor calibration - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_NF); + /* keep last value if calibration hasn't completed */ + if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "NF did not complete in calibration window\n"); - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_NF, 0, false); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "noise floor calibration timeout (%uMHz)\n", freq); - return -EAGAIN; + return; } - /* Wait until the noise floor is calibrated and read the value */ - for (i = 20; i > 0; i--) { - mdelay(1); - noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); - noise_floor = AR5K_PHY_NF_RVAL(noise_floor); - if (noise_floor & AR5K_PHY_NF_ACTIVE) { - noise_floor = AR5K_PHY_NF_AVAL(noise_floor); - - if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) - break; - } + switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + case CHANNEL_T: + case CHANNEL_XR: + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + case CHANNEL_TG: + ee_mode = AR5K_EEPROM_MODE_11G; + break; + default: + case CHANNEL_B: + ee_mode = AR5K_EEPROM_MODE_11B; + break; } - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, - "noise floor %d\n", noise_floor); - if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { - ATH5K_ERR(ah->ah_sc, - "noise floor calibration failed (%uMHz)\n", freq); - return -EAGAIN; + /* completed NF calibration, test threshold */ + nf = ath5k_hw_read_measured_noise_floor(ah); + threshold = ee->ee_noise_floor_thr[ee_mode]; + + if (nf > threshold) { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "noise floor failure detected; " + "read %d, threshold %d\n", + nf, threshold); + + nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE; } - ah->ah_noise_floor = noise_floor; + ath5k_hw_update_nfcal_hist(ah, nf); + nf = ath5k_hw_get_median_noise_floor(ah); - return 0; + /* load noise floor (in .5 dBm) so the hardware will use it */ + val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M; + val |= (nf * 2) & AR5K_PHY_NF_M; + ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); + + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, + ~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE)); + + ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, + 0, false); + + /* + * Load a high max CCA Power value (-50 dBm in .5 dBm units) + * so that we're not capped by the median we just loaded. + * This will be used as the initial value for the next noise + * floor calibration. + */ + val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M); + ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_NF_EN | + AR5K_PHY_AGCCTL_NF_NOUPDATE | + AR5K_PHY_AGCCTL_NF); + + ah->ah_noise_floor = nf; + + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "noise floor calibrated: %d\n", nf); } /* @@ -1287,7 +1358,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, return ret; } - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + ath5k_hw_update_noise_floor(ah); /* * Re-enable RX/TX and beacons @@ -1360,7 +1431,7 @@ done: * since noise floor calibration interrupts rx path while I/Q * calibration doesn't. We don't need to run noise floor calibration * as often as I/Q calibration.*/ - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + ath5k_hw_update_noise_floor(ah); /* Initiate a gain_F calibration */ ath5k_hw_request_rfgain_probe(ah); diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index c63ea6a..4cb9c5d 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -35,7 +35,7 @@ * released by Atheros and on various debug messages found on the net. */ - +#include "../reg.h" /*====MAC DMA REGISTERS====*/ @@ -1650,12 +1650,6 @@ #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 * * XXX: PCDAC steps (0.5dbm) or DBM ? @@ -2039,17 +2033,14 @@ #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ /* - * PHY noise floor status register + * PHY noise floor status register (CCA = Clear Channel Assessment) */ #define AR5K_PHY_NF 0x9864 /* Register address */ -#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ -#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ -#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) -#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) -#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) +#define AR5K_PHY_NF_M 0x000001ff /* Noise floor, written to hardware in 1/2 dBm units */ +#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) #define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ #define AR5K_PHY_NF_THRESH62_S 12 -#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ +#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* Minimum measured noise level, read from hardware in 1 dBm units */ #define AR5K_PHY_NF_MINCCA_PWR_S 19 /* diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 34e13c7..62954fc 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -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); @@ -1289,7 +1293,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * out and/or noise floor calibration might timeout. */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL); + AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); /* At the same time start I/Q calibration for QAM constellation * -no need for CCK- */ @@ -1310,21 +1314,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, channel->center_freq); } - /* - * If we run NF calibration before AGC, it always times out. - * Binary HAL starts NF and AGC calibration at the same time - * and only waits for AGC to finish. Also if AGC or NF cal. - * times out, reset doesn't fail on binary HAL. I believe - * that's wrong because since rx path is routed to a detector, - * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211 - * enables noise floor calibration after offset calibration and if noise - * floor calibration fails, reset fails. I believe that's - * a better approach, we just need to find a polling interval - * that suits best, even if reset continues we need to make - * sure that rx path is ready. - */ - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - /* Restore antenna mode */ ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index ef5f59c..b735fb3 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -1,6 +1,10 @@ +config ATH9K_HW + tristate + config ATH9K tristate "Atheros 802.11n wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 + depends on PCI && MAC80211 + 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 diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index ff2c9a2..8caf2a8 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -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 diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 2ad7d02..329e6bc 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -22,27 +22,29 @@ #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_softc *sc = (struct ath_softc *)common->priv; 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_softc *sc = ah->ah_sc; + struct ath_softc *sc = (struct ath_softc *)common->priv; 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; } @@ -67,6 +69,7 @@ static int ath_ahb_probe(struct platform_device *pdev) int irq; int ret = 0; struct ath_hw *ah; + char hw_name[64]; if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "no platform data specified\n"); @@ -116,10 +119,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; @@ -132,14 +134,11 @@ static int ath_ahb_probe(struct platform_device *pdev) } ah = sc->sc_ah; + ath9k_hw_name(ah, hw_name, sizeof(hw_name)); printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x, " - "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n", + "%s: %s mem=0x%lx, irq=%d\n", wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev, + hw_name, (unsigned long)mem, irq); return 0; diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2b49374..2a0cd64 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1d59f10..13dd020 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -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) -{ - return &ah->ah_sc->common; -} - -static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) +static inline void ath_read_cachesize(struct ath_common *common, int *csz) { - return &(ath9k_hw_common(ah)->regulatory); + common->bus_ops->read_cachesize(common, csz); } -static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) +static inline void ath_bus_cleanup(struct ath_common *common) { - 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 */ diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 45c4ea5..b10c884f 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -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; } diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 55f607b..fb4ac15 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -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; + for (i = 0; i < 32; i++) + ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; +} +EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); - btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; +void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah) +{ + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * - btcoex_info->btcoex_period / 100; + /* 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)); - for (i = 0; i < 32; i++) - hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); - setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer, - (unsigned long) hw->ah_sc); + /* 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); - 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); + /* 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; - if (btcoex_info->no_stomp_timer == NULL) - return -ENOMEM; + /* 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)); - spin_lock_init(&btcoex_info->btcoex_lock); + /* 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); - return 0; + 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); -int ath9k_hw_btcoex_init(struct ath_hw *ah) +static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah) { - struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; - int ret = 0; - - 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)); - - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); - - /* 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); - - /* 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)); - - /* 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); - } + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - return ret; + /* 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); } -void ath9k_hw_btcoex_enable(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; - - 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); - } + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - REG_RMW(ah, AR_GPIO_PDPU, - (0x2 << (btcoex_info->btactive_gpio * 2)), - (0x3 << (btcoex_info->btactive_gpio * 2))); - - ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED; + 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); -void ath9k_hw_btcoex_disable(struct ath_hw *ah) +static void ath9k_hw_btcoex_enable_3wire(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); + /* + * 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); - ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + 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); - if (btcoex_info->btcoex_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; + ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, + AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); } -/* - * Pause btcoex timer and bt duty cycle timer - */ -void ath_btcoex_timer_pause(struct ath_softc *sc, - struct ath_btcoex_info *btinfo) +void ath9k_hw_btcoex_enable(struct ath_hw *ah) { + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - del_timer_sync(&btinfo->period_timer); + 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; + } - if (btinfo->hw_timer_enabled) - ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); + REG_RMW(ah, AR_GPIO_PDPU, + (0x2 << (btcoex_hw->btactive_gpio * 2)), + (0x3 << (btcoex_hw->btactive_gpio * 2))); - btinfo->hw_timer_enabled = false; + ah->btcoex_hw.enabled = true; } +EXPORT_SYMBOL(ath9k_hw_btcoex_enable); -/* - * (Re)start btcoex timers - */ -void ath_btcoex_timer_resume(struct ath_softc *sc, - struct ath_btcoex_info *btinfo) +void ath9k_hw_btcoex_disable(struct ath_hw *ah) { + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers"); + ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0); - /* 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); + ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - btinfo->bt_priority_cnt = 0; - btinfo->bt_priority_time = jiffies; - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; + 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); + } - mod_timer(&btinfo->period_timer, jiffies); + ah->btcoex_hw.enabled = false; } +EXPORT_SYMBOL(ath9k_hw_btcoex_disable); diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 297b027..1ba31a7 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -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 diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 0ad6d0b..238a574 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -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); - - 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, + "Starting ADC Gain Cal for Chain %d\n", i); + + 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); - - 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, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + 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,51 +747,73 @@ 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; - - 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); + 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; + + REG_RMW_FIELD(ah, + AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); + } } } } } -static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) +static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) { u32 regVal; unsigned int i; @@ -845,7 +877,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); /* find off_6_1; */ - for (i = 6; i >= 0; i--) { + for (i = 6; i > 0; i--) { regVal = REG_READ(ah, 0x7834); regVal |= (1 << (20 + i)); REG_WRITE(ah, 0x7834, regVal); @@ -857,10 +889,19 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) REG_WRITE(ah, 0x7834, regVal); } - /* Empirical offset correction */ -#if 0 - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20); -#endif + regVal = (regVal >>20) & 0x7f; + + /* Update PA cal info */ + if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { + if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) + ah->pacal_info.max_skipcount = + 2 * ah->pacal_info.max_skipcount; + ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; + } else { + ah->pacal_info.max_skipcount = 1; + ah->pacal_info.skipcount = 0; + ah->pacal_info.prev_offset = regVal; + } regVal = REG_READ(ah, 0x7834); regVal |= 0x1; @@ -875,7 +916,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 +930,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) == @@ -1011,7 +1052,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, if (longcal) { /* Do periodic PAOffset Cal */ if (AR_SREV_9271(ah)) - ath9k_hw_9271_pa_cal(ah); + ath9k_hw_9271_pa_cal(ah, false); else if (AR_SREV_9285_11_OR_LATER(ah)) { if (!ah->pacal_info.skipcount) ath9k_hw_9285_pa_cal(ah, false); @@ -1036,9 +1077,13 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, return iscaldone; } +EXPORT_SYMBOL(ath9k_hw_calibrate); +/* Carrier leakage Calibration fix */ 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 +1094,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 +1109,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,7 +1123,9 @@ 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) { - if (AR_SREV_9285_12_OR_LATER(ah)) { + struct ath_common *common = ath9k_hw_common(ah); + + if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { if (!ar9285_clc(ah, chan)) return false; } else { @@ -1098,9 +1145,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; } @@ -1114,7 +1161,9 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) } /* Do PA Calibration */ - if (AR_SREV_9285_11_OR_LATER(ah)) + if (AR_SREV_9271(ah)) + ath9k_hw_9271_pa_cal(ah, true); + else if (AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah, true); /* Do NF Calibration after DC offset and other calibrations */ @@ -1128,20 +1177,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; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 9028ab1..b2c873e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 2be4c22..84f4426 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 7241f47..749e85d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -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) { } diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index b6e52d0..dacaae9 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -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, diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 4fe33f7..2f2993b 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index b8eca7b..68db166 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -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 */ @@ -1107,6 +1112,10 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); + + if (AR_SREV_9271_10(ah)) + REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, pModal->thresh62); REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, @@ -1148,20 +1157,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; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index c20c21a..839d05a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -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); - - 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; } @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 4071fc9..404a034 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ca7694c..111ff04 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -16,9 +16,9 @@ #include <linux/io.h> #include <asm/unaligned.h> -#include <linux/pci.h> -#include "ath9k.h" +#include "hw.h" +#include "rc.h" #include "initvals.h" #define ATH9K_CLOCK_RATE_CCK 22 @@ -26,13 +26,27 @@ #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode); +static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, struct ar5416_eeprom_def *pEepData, u32 reg, u32 value); -static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); -static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); + +MODULE_AUTHOR("Atheros Communications"); +MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); +MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); +MODULE_LICENSE("Dual BSD/GPL"); + +static int __init ath9k_init(void) +{ + return 0; +} +module_init(ath9k_init); + +static void __exit ath9k_exit(void) +{ + return; +} +module_exit(ath9k_exit); /********************/ /* Helper Functions */ @@ -40,7 +54,7 @@ static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) { - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; if (!ah->curchan) /* should really check for CCK instead */ return clks / ATH9K_CLOCK_RATE_CCK; @@ -52,7 +66,7 @@ static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) { - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; if (conf_is_ht40(conf)) return ath9k_hw_mac_usec(ah, clks) / 2; @@ -62,7 +76,7 @@ static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) { - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; if (!ah->curchan) /* should really check for CCK instead */ return usecs *ATH9K_CLOCK_RATE_CCK; @@ -73,7 +87,7 @@ static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) { - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; if (conf_is_ht40(conf)) return ath9k_hw_mac_clks(ah, usecs) * 2; @@ -81,38 +95,6 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) return ath9k_hw_mac_clks(ah, usecs); } -/* - * Read and write, they both share the same lock. We do this to serialize - * reads and writes on Atheros 802.11n PCI devices only. This is required - * as the FIFO on these devices can only accept sanely 2 requests. After - * that the device goes bananas. Serializing the reads/writes prevents this - * from happening. - */ - -void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) -{ - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - iowrite32(val, ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - iowrite32(val, ah->ah_sc->mem + reg_offset); -} - -unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) -{ - u32 val; - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - val = ioread32(ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - val = ioread32(ah->ah_sc->mem + reg_offset); - return val; -} - bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) { int i; @@ -126,12 +108,13 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) udelay(AH_TIME_QUANTUM); } - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", - timeout, reg, REG_READ(ah, reg), mask, val); + ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, + "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", + timeout, reg, REG_READ(ah, reg), mask, val); return false; } +EXPORT_SYMBOL(ath9k_hw_wait); u32 ath9k_hw_reverse_bits(u32 val, u32 n) { @@ -210,15 +193,16 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, } break; default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unknown phy %u (rate ix %u)\n", - rates->info[rateix].phy, rateix); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Unknown phy %u (rate ix %u)\n", + rates->info[rateix].phy, rateix); txTime = 0; break; } return txTime; } +EXPORT_SYMBOL(ath9k_hw_computetxtime); void ath9k_hw_get_channel_centers(struct ath_hw *ah, struct ath9k_channel *chan, @@ -245,10 +229,9 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah, centers->ctl_center = centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); + /* 25 MHz spacing is supported by hw but not on upper layers */ centers->ext_center = - centers->synth_center + (extoff * - ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ? - HT40_CHANNEL_CENTER_SHIFT : 15)); + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); } /******************/ @@ -317,6 +300,7 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) static bool ath9k_hw_chip_test(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; u32 regHold[2]; u32 patternData[4] = { 0x55555555, @@ -335,10 +319,11 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (rdData != wrData) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", - addr, wrData, rdData); + ath_print(common, ATH_DBG_FATAL, + "address test failed " + "addr: 0x%08x - wr:0x%08x != " + "rd:0x%08x\n", + addr, wrData, rdData); return false; } } @@ -347,10 +332,11 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (wrData != rdData) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", - addr, wrData, rdData); + ath_print(common, ATH_DBG_FATAL, + "address test failed " + "addr: 0x%08x - wr:0x%08x != " + "rd:0x%08x\n", + addr, wrData, rdData); return false; } } @@ -433,6 +419,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) if (num_possible_cpus() > 1) ah->config.serialize_regmode = SER_REG_MODE_AUTO; } +EXPORT_SYMBOL(ath9k_hw_init); static void ath9k_hw_init_defaults(struct ath_hw *ah) { @@ -465,21 +452,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->power_mode = ATH9K_PM_UNDEFINED; } -static int ath9k_hw_rfattach(struct ath_hw *ah) -{ - bool rfStatus = false; - int ecode = 0; - - rfStatus = ath9k_hw_init_rf(ah, &ecode); - if (!rfStatus) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "RF setup failed, status: %u\n", ecode); - return ecode; - } - - return 0; -} - static int ath9k_hw_rf_claim(struct ath_hw *ah) { u32 val; @@ -497,9 +469,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) case AR_RAD2122_SREV_MAJOR: break; default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Radio Chip Rev 0x%02X not supported\n", - val & AR_RADIO_SREV_MAJOR); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Radio Chip Rev 0x%02X not supported\n", + val & AR_RADIO_SREV_MAJOR); return -EOPNOTSUPP; } @@ -510,6 +482,7 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) static int ath9k_hw_init_macaddr(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); u32 sum; int i; u16 eeval; @@ -518,8 +491,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) for (i = 0; i < 3; i++) { eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); sum += eeval; - ah->macaddr[2 * i] = eeval >> 8; - ah->macaddr[2 * i + 1] = eeval & 0xff; + common->macaddr[2 * i] = eeval >> 8; + common->macaddr[2 * i + 1] = eeval & 0xff; } if (sum == 0 || sum == 0xffff * 3) return -EADDRNOTAVAIL; @@ -590,12 +563,20 @@ static int ath9k_hw_post_init(struct ath_hw *ah) if (ecode != 0) return ecode; - DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", - ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - - ecode = ath9k_hw_rfattach(ah); - if (ecode != 0) - return ecode; + ath_print(ath9k_hw_common(ah), ATH_DBG_CONFIG, + "Eeprom VER: %d, REV: %d\n", + ah->eep_ops->get_eeprom_ver(ah), + ah->eep_ops->get_eeprom_rev(ah)); + + if (!AR_SREV_9280_10_OR_LATER(ah)) { + ecode = ath9k_hw_rf_alloc_ext_banks(ah); + if (ecode) { + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Failed allocating banks for " + "external radio\n"); + return ecode; + } + } if (!AR_SREV_9100(ah)) { ath9k_hw_ani_setup(ah); @@ -617,6 +598,7 @@ static bool ath9k_hw_devid_supported(u16 devid) case AR9285_DEVID_PCIE: case AR5416_DEVID_AR9287_PCI: case AR5416_DEVID_AR9287_PCIE: + case AR9271_USB: return true; default: break; @@ -634,9 +616,8 @@ static bool ath9k_hw_macversion_supported(u32 macversion) case AR_SREV_VERSION_9280: case AR_SREV_VERSION_9285: case AR_SREV_VERSION_9287: - return true; - /* Not yet */ case AR_SREV_VERSION_9271: + return true; default: break; } @@ -670,10 +651,13 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah) static void ath9k_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0, - ARRAY_SIZE(ar9271Modes_9271_1_0), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0, - ARRAY_SIZE(ar9271Common_9271_1_0), 2); + INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, + ARRAY_SIZE(ar9271Modes_9271), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, + ARRAY_SIZE(ar9271Common_9271), 2); + INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, + ar9271Modes_9271_1_0_only, + ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); return; } @@ -905,21 +889,27 @@ static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah) int ath9k_hw_init(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); int r = 0; - if (!ath9k_hw_devid_supported(ah->hw_version.devid)) + if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { + ath_print(common, ATH_DBG_FATAL, + "Unsupported device ID: 0x%0x\n", + ah->hw_version.devid); return -EOPNOTSUPP; + } ath9k_hw_init_defaults(ah); ath9k_hw_init_config(ah); if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); + ath_print(common, ATH_DBG_FATAL, + "Couldn't reset chip\n"); return -EIO; } if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); + ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); return -EIO; } @@ -934,14 +924,14 @@ int ath9k_hw_init(struct ath_hw *ah) } } - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n", + ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n", ah->config.serialize_regmode); if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Mac Chip Rev 0x%02x.%x is not supported by " - "this driver\n", ah->hw_version.macVersion, - ah->hw_version.macRev); + ath_print(common, ATH_DBG_FATAL, + "Mac Chip Rev 0x%02x.%x is not supported by " + "this driver\n", ah->hw_version.macVersion, + ah->hw_version.macRev); return -EOPNOTSUPP; } @@ -959,8 +949,14 @@ int ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_cal_settings(ah); ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_10_OR_LATER(ah)) { ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; + ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel; + ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate; + } else { + ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel; + ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate; + } ath9k_hw_init_mode_regs(ah); @@ -969,6 +965,16 @@ int ath9k_hw_init(struct ath_hw *ah) else ath9k_hw_disablepcie(ah); + /* Support for Japan ch.14 (2484) spread */ + if (AR_SREV_9287_11_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniCckfirNormal, + ar9287Common_normal_cck_fir_coeff_92871_1, + ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), 2); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9287Common_japan_2484_cck_fir_coeff_92871_1, + ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), 2); + } + r = ath9k_hw_post_init(ah); if (r) return r; @@ -979,8 +985,8 @@ int ath9k_hw_init(struct ath_hw *ah) r = ath9k_hw_init_macaddr(ah); if (r) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to initialize MAC address\n"); + ath_print(common, ATH_DBG_FATAL, + "Failed to initialize MAC address\n"); return r; } @@ -991,6 +997,8 @@ int ath9k_hw_init(struct ath_hw *ah) ath9k_init_nfcal_hist_buffer(ah); + common->state = ATH_HW_INITIALIZED; + return 0; } @@ -1027,6 +1035,22 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); } +static void ath9k_hw_change_target_baud(struct ath_hw *ah, u32 freq, u32 baud) +{ + u32 lcr; + u32 baud_divider = freq * 1000 * 1000 / 16 / baud; + + lcr = REG_READ(ah , 0x5100c); + lcr |= 0x80; + + REG_WRITE(ah, 0x5100c, lcr); + REG_WRITE(ah, 0x51004, (baud_divider >> 8)); + REG_WRITE(ah, 0x51000, (baud_divider & 0xff)); + + lcr &= ~0x80; + REG_WRITE(ah, 0x5100c, lcr); +} + static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -1090,6 +1114,26 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, } REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + /* Switch the core clock for ar9271 to 117Mhz */ + if (AR_SREV_9271(ah)) { + if ((pll == 0x142c) || (pll == 0x2850) ) { + udelay(500); + /* set CLKOBS to output AHB clock */ + REG_WRITE(ah, 0x7020, 0xe); + /* + * 0x304: 117Mhz, ahb_ratio: 1x1 + * 0x306: 40Mhz, ahb_ratio: 1x1 + */ + REG_WRITE(ah, 0x50040, 0x304); + /* + * makes adjustments for the baud dividor to keep the + * targetted baud rate based on the used core clock. + */ + ath9k_hw_change_target_baud(ah, AR9271_CORE_CLOCK, + AR9271_TARGET_BAUD_RATE); + } + } + udelay(RTC_PLL_SETTLE_DELAY); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); @@ -1164,7 +1208,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) { if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, + "bad ack timeout %u\n", us); ah->acktimeout = (u32) -1; return false; } else { @@ -1178,7 +1223,8 @@ static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) { if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, + "bad cts timeout %u\n", us); ah->ctstimeout = (u32) -1; return false; } else { @@ -1192,8 +1238,8 @@ static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) { if (tu > 0xFFFF) { - DPRINTF(ah->ah_sc, ATH_DBG_XMIT, - "bad global tx timeout %u\n", tu); + ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, + "bad global tx timeout %u\n", tu); ah->globaltxtimeout = (u32) -1; return false; } else { @@ -1205,8 +1251,8 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) static void ath9k_hw_init_user_settings(struct ath_hw *ah) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n", - ah->misc_mode); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", + ah->misc_mode); if (ah->misc_mode != 0) REG_WRITE(ah, AR_PCU_MISC, @@ -1229,14 +1275,23 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid) void ath9k_hw_detach(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); + + if (common->state <= ATH_HW_INITIALIZED) + goto free_hw; + if (!AR_SREV_9100(ah)) ath9k_hw_ani_disable(ah); - ath9k_hw_rf_free(ah); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + +free_hw: + if (!AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_rf_free_ext_banks(ah); kfree(ah); ah = NULL; } +EXPORT_SYMBOL(ath9k_hw_detach); /*******/ /* INI */ @@ -1254,7 +1309,8 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, * AR9271 1.1 */ if (AR_SREV_9271_10(ah)) { - val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE; + val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | + AR_PHY_SPECTRAL_SCAN_ENABLE; REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); } else if (AR_SREV_9271_11(ah)) @@ -1298,28 +1354,29 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, u32 reg, u32 value) { struct base_eep_header *pBase = &(pEepData->baseEepHeader); + struct ath_common *common = ath9k_hw_common(ah); switch (ah->hw_version.devid) { case AR9280_DEVID_PCI: if (reg == 0x7894) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + ath_print(common, ATH_DBG_EEPROM, "ini VAL: %x EEPROM: %x\n", value, (pBase->version & 0xff)); if ((pBase->version & 0xff) > 0x0a) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PWDCLKIND: %d\n", - pBase->pwdclkind); + ath_print(common, ATH_DBG_EEPROM, + "PWDCLKIND: %d\n", + pBase->pwdclkind); value &= ~AR_AN_TOP2_PWDCLKIND; value |= AR_AN_TOP2_PWDCLKIND & (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); } else { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PWDCLKIND Earlier Rev\n"); + ath_print(common, ATH_DBG_EEPROM, + "PWDCLKIND Earlier Rev\n"); } - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "final ini VAL: %x\n", value); + ath_print(common, ATH_DBG_EEPROM, + "final ini VAL: %x\n", value); } break; } @@ -1374,8 +1431,7 @@ static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, } static int ath9k_hw_process_ini(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) + struct ath9k_channel *chan) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); int i, regWrites = 0; @@ -1469,7 +1525,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, DO_DELAY(regWrites); } - ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); + ath9k_hw_write_regs(ah, freqIndex, regWrites); + + if (AR_SREV_9271_10(ah)) + REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, + modesIndex, regWrites); if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, @@ -1477,7 +1537,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, } ath9k_hw_override_ini(ah, chan); - ath9k_hw_set_regs(ah, chan, macmode); + ath9k_hw_set_regs(ah, chan); ath9k_hw_init_chain_masks(ah); if (OLC_FOR_AR9280_20_LATER) @@ -1491,8 +1551,8 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, (u32) regulatory->power_limit)); if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "ar5416SetRfRegs failed\n"); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "ar5416SetRfRegs failed\n"); return -EIO; } @@ -1697,16 +1757,14 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) REG_WRITE(ah, AR_RTC_RC, 0); if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "RTC stuck in MAC reset\n"); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, + "RTC stuck in MAC reset\n"); return false; } if (!AR_SREV_9100(ah)) REG_WRITE(ah, AR_RC, 0); - ath9k_hw_init_pll(ah, NULL); - if (AR_SREV_9100(ah)) udelay(50); @@ -1734,7 +1792,8 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) AR_RTC_STATUS_M, AR_RTC_STATUS_ON, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, + "RTC not waking up\n"); return false; } @@ -1759,8 +1818,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) } } -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) +static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan) { u32 phymode; u32 enableDacFifo = 0; @@ -1779,12 +1837,10 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, (chan->chanmode == CHANNEL_G_HT40PLUS)) phymode |= AR_PHY_FC_DYN2040_PRI_CH; - if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25) - phymode |= AR_PHY_FC_DYN2040_EXT_CH; } REG_WRITE(ah, AR_PHY_TURBO, phymode); - ath9k_hw_set11nmac2040(ah, macmode); + ath9k_hw_set11nmac2040(ah); REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); @@ -1810,17 +1866,19 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, } static bool ath9k_hw_channel_change(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) + struct ath9k_channel *chan) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *channel = chan->chan; u32 synthDelay, qnum; + int r; for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { if (ath9k_hw_numtxpending(ah, qnum)) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "Transmit frames pending on queue %d\n", qnum); + ath_print(common, ATH_DBG_QUEUE, + "Transmit frames pending on " + "queue %d\n", qnum); return false; } } @@ -1828,21 +1886,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Could not kill baseband RX\n"); + ath_print(common, ATH_DBG_FATAL, + "Could not kill baseband RX\n"); return false; } - ath9k_hw_set_regs(ah, chan, macmode); + ath9k_hw_set_regs(ah, chan); - if (AR_SREV_9280_10_OR_LATER(ah)) { - ath9k_hw_ar9280_set_channel(ah, chan); - } else { - if (!(ath9k_hw_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to set channel\n"); - return false; - } + r = ah->ath9k_hw_rf_set_freq(ah, chan); + if (r) { + ath_print(common, ATH_DBG_FATAL, + "Failed to set channel\n"); + return false; } ah->eep_ops->set_txpower(ah, chan, @@ -1865,10 +1920,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_9280_spur_mitigate(ah, chan); - else - ath9k_hw_spur_mitigate(ah, chan); + ah->ath9k_hw_spur_mitigate_freq(ah, chan); if (!chan->oneTimeCalsDone) chan->oneTimeCalsDone = true; @@ -1876,457 +1928,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return true; } -static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int freq; - int bin, cur_bin; - int bb_spur_off, spur_subchannel_sd; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, newVal; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - struct chan_centers centers; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - ah->config.spurmode = SPUR_ENABLE_EEPROM; - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - - if (is2GHz) - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; - else - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; - - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - freq; - - if (IS_CHAN_HT40(chan)) { - if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { - bb_spur = cur_bb_spur; - break; - } - } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - return; - } else { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - } - - bin = bb_spur * 320; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - - newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); - - newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); - - if (IS_CHAN_HT40(chan)) { - if (bb_spur < 0) { - spur_subchannel_sd = 1; - bb_spur_off = bb_spur + 10; - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur - 10; - } - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur; - } - - if (IS_CHAN_HT40(chan)) - spur_delta_phase = - ((bb_spur * 262144) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - else - spur_delta_phase = - ((bb_spur * 524288) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; - spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; - - newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, newVal); - - newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; - REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int bin, cur_bin; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, new; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - (chan->channel * 10); - if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) - return; - - bin = bb_spur * 32; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); - - new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, new); - - spur_delta_phase = ((bb_spur * 524288) / 100) & - AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; - spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; - - new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, new); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - static void ath9k_enable_rfkill(struct ath_hw *ah) { REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, @@ -2342,17 +1943,16 @@ static void ath9k_enable_rfkill(struct ath_hw *ah) int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange) { + struct ath_common *common = ath9k_hw_common(ah); u32 saveLedState; - struct ath_softc *sc = ah->ah_sc; struct ath9k_channel *curchan = ah->curchan; u32 saveDefAntenna; u32 macStaId1; u64 tsf = 0; int i, rx_chainmask, r; - ah->extprotspacing = sc->ht_extprotspacing; - ah->txchainmask = sc->tx_chainmask; - ah->rxchainmask = sc->rx_chainmask; + ah->txchainmask = common->tx_chainmask; + ah->rxchainmask = common->rx_chainmask; if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; @@ -2369,7 +1969,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { - if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { + if (ath9k_hw_channel_change(ah, chan)) { ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah); return 0; @@ -2400,7 +2000,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, } if (!ath9k_hw_chip_reset(ah, chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); + ath_print(common, ATH_DBG_FATAL, "Chip reset failed\n"); return -EINVAL; } @@ -2429,7 +2029,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); } - r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); + r = ath9k_hw_process_ini(ah, chan); if (r) return r; @@ -2453,17 +2053,14 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_9280_spur_mitigate(ah, chan); - else - ath9k_hw_spur_mitigate(ah, chan); - + ah->ath9k_hw_spur_mitigate_freq(ah, chan); ah->eep_ops->set_board_values(ah, chan); - ath9k_hw_decrease_chain_power(ah, chan); + if (AR_SREV_5416(ah)) + ath9k_hw_decrease_chain_power(ah, chan); - REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr)); - REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4) + REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); + REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | macStaId1 | AR_STA_ID1_RTS_USE_DEF | (ah->config. @@ -2471,24 +2068,19 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | ah->sta_id1_defaults); ath9k_hw_set_operating_mode(ah, ah->opmode); - REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); - REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); + ath_hw_setbssidmask(common); REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); - REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); - REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | - ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); + ath9k_hw_write_associd(ah); REG_WRITE(ah, AR_ISR, ~0); REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_ar9280_set_channel(ah, chan); - else - if (!(ath9k_hw_set_channel(ah, chan))) - return -EIO; + r = ah->ath9k_hw_rf_set_freq(ah, chan); + if (r) + return r; for (i = 0; i < AR_NUM_DCU; i++) REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); @@ -2558,13 +2150,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u32 mask; mask = REG_READ(ah, AR_CFG); if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, + ath_print(common, ATH_DBG_RESET, "CFG Byte Swap Set 0x%x\n", mask); } else { mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; REG_WRITE(ah, AR_CFG, mask); - DPRINTF(ah->ah_sc, ATH_DBG_RESET, + ath_print(common, ATH_DBG_RESET, "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); } } else { @@ -2577,11 +2169,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, #endif } - if (ah->ah_sc->sc_flags & SC_OP_BTCOEX_ENABLED) + if (ah->btcoex_hw.enabled) ath9k_hw_btcoex_enable(ah); return 0; } +EXPORT_SYMBOL(ath9k_hw_reset); /************************/ /* Key Cache Management */ @@ -2592,8 +2185,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) u32 keyType; if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); return false; } @@ -2620,14 +2213,15 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) return true; } +EXPORT_SYMBOL(ath9k_hw_keyreset); bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) { u32 macHi, macLo; if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); return false; } @@ -2648,18 +2242,20 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) return true; } +EXPORT_SYMBOL(ath9k_hw_keysetmac); bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, const struct ath9k_keyval *k, const u8 *mac) { const struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath_common *common = ath9k_hw_common(ah); u32 key0, key1, key2, key3, key4; u32 keyType; if (entry >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keycache entry %u out of range\n", entry); + ath_print(common, ATH_DBG_FATAL, + "keycache entry %u out of range\n", entry); return false; } @@ -2669,9 +2265,9 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, break; case ATH9K_CIPHER_AES_CCM: if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "AES-CCM not supported by mac rev 0x%x\n", - ah->hw_version.macRev); + ath_print(common, ATH_DBG_ANY, + "AES-CCM not supported by mac rev 0x%x\n", + ah->hw_version.macRev); return false; } keyType = AR_KEYTABLE_TYPE_CCM; @@ -2680,15 +2276,15 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, keyType = AR_KEYTABLE_TYPE_TKIP; if (ATH9K_IS_MIC_ENABLED(ah) && entry + 64 >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "entry %u inappropriate for TKIP\n", entry); + ath_print(common, ATH_DBG_ANY, + "entry %u inappropriate for TKIP\n", entry); return false; } break; case ATH9K_CIPHER_WEP: if (k->kv_len < WLAN_KEY_LEN_WEP40) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "WEP key length %u too small\n", k->kv_len); + ath_print(common, ATH_DBG_ANY, + "WEP key length %u too small\n", k->kv_len); return false; } if (k->kv_len <= WLAN_KEY_LEN_WEP40) @@ -2702,8 +2298,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, keyType = AR_KEYTABLE_TYPE_CLR; break; default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "cipher %u not supported\n", k->kv_type); + ath_print(common, ATH_DBG_FATAL, + "cipher %u not supported\n", k->kv_type); return false; } @@ -2845,6 +2441,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, return true; } +EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) { @@ -2855,6 +2452,7 @@ bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) } return false; } +EXPORT_SYMBOL(ath9k_hw_keyisvalid); /******************************/ /* Power Management (Chipset) */ @@ -2869,8 +2467,9 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) if (!AR_SREV_9100(ah)) REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - REG_CLR_BIT(ah, (AR_RTC_RESET), - AR_RTC_RESET_EN); + if(!AR_SREV_5416(ah)) + REG_CLR_BIT(ah, (AR_RTC_RESET), + AR_RTC_RESET_EN); } } @@ -2902,6 +2501,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) ATH9K_RESET_POWER_ON) != true) { return false; } + ath9k_hw_init_pll(ah, NULL); } if (AR_SREV_9100(ah)) REG_SET_BIT(ah, AR_RTC_RESET, @@ -2920,8 +2520,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) AR_RTC_FORCE_WAKE_EN); } if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Failed to wakeup in %uus\n", + POWER_UP_TIME / 20); return false; } } @@ -2931,9 +2532,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) return true; } -static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, - enum ath9k_power_mode mode) +bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) { + struct ath_common *common = ath9k_hw_common(ah); int status = true, setChip = true; static const char *modes[] = { "AWAKE", @@ -2945,8 +2546,8 @@ static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, if (ah->power_mode == mode) return status; - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", - modes[ah->power_mode], modes[mode]); + ath_print(common, ATH_DBG_RESET, "%s -> %s\n", + modes[ah->power_mode], modes[mode]); switch (mode) { case ATH9K_PM_AWAKE: @@ -2960,59 +2561,15 @@ static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, ath9k_set_power_network_sleep(ah, setChip); break; default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unknown power mode %u\n", mode); + ath_print(common, ATH_DBG_FATAL, + "Unknown power mode %u\n", mode); return false; } ah->power_mode = mode; return status; } - -bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags); - ret = ath9k_hw_setpower_nolock(ah, mode); - spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags); - - return ret; -} - -void ath9k_ps_wakeup(struct ath_softc *sc) -{ - unsigned long flags; - - spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (++sc->ps_usecount != 1) - goto unlock; - - ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); - - unlock: - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); -} - -void ath9k_ps_restore(struct ath_softc *sc) -{ - unsigned long flags; - - spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (--sc->ps_usecount != 0) - goto unlock; - - if (sc->ps_enabled && - !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK))) - ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); - - unlock: - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); -} +EXPORT_SYMBOL(ath9k_hw_setpower); /* * Helper for ASPM support. @@ -3145,6 +2702,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) } } } +EXPORT_SYMBOL(ath9k_hw_configpcipowersave); /**********************/ /* Interrupt Handling */ @@ -3168,6 +2726,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) return false; } +EXPORT_SYMBOL(ath9k_hw_intrpend); bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) { @@ -3176,6 +2735,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) struct ath9k_hw_capabilities *pCap = &ah->caps; u32 sync_cause = 0; bool fatal_int = false; + struct ath_common *common = ath9k_hw_common(ah); if (!AR_SREV_9100(ah)) { if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { @@ -3249,8 +2809,8 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) } if (isr & AR_ISR_RXORN) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "receive FIFO overrun interrupt\n"); + ath_print(common, ATH_DBG_INTERRUPT, + "receive FIFO overrun interrupt\n"); } if (!AR_SREV_9100(ah)) { @@ -3292,25 +2852,25 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) if (fatal_int) { if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "received PCI FATAL interrupt\n"); + ath_print(common, ATH_DBG_ANY, + "received PCI FATAL interrupt\n"); } if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "received PCI PERR interrupt\n"); + ath_print(common, ATH_DBG_ANY, + "received PCI PERR interrupt\n"); } *masked |= ATH9K_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); REG_WRITE(ah, AR_RC, 0); *masked |= ATH9K_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + ath_print(common, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); } REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); @@ -3319,17 +2879,19 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) return true; } +EXPORT_SYMBOL(ath9k_hw_getisr); enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) { u32 omask = ah->mask_reg; u32 mask, mask2; struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath_common *common = ath9k_hw_common(ah); - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); + ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); if (omask & ATH9K_INT_GLOBAL) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n"); + ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_DISABLE); (void) REG_READ(ah, AR_IER); if (!AR_SREV_9100(ah)) { @@ -3386,7 +2948,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) mask2 |= AR_IMR_S2_CST; } - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); + ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); REG_WRITE(ah, AR_IMR, mask); mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | @@ -3406,7 +2968,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) } if (ints & ATH9K_INT_GLOBAL) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n"); + ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_ENABLE); if (!AR_SREV_9100(ah)) { REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, @@ -3419,12 +2981,13 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) REG_WRITE(ah, AR_INTR_SYNC_MASK, AR_INTR_SYNC_DEFAULT); } - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); + ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); } return omask; } +EXPORT_SYMBOL(ath9k_hw_set_interrupts); /*******************/ /* Beacon Handling */ @@ -3467,9 +3030,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; break; default: - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, - "%s: unsupported opmode: %d\n", - __func__, ah->opmode); + ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON, + "%s: unsupported opmode: %d\n", + __func__, ah->opmode); return; break; } @@ -3481,18 +3044,19 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) beacon_period &= ~ATH9K_BEACON_ENA; if (beacon_period & ATH9K_BEACON_RESET_TSF) { - beacon_period &= ~ATH9K_BEACON_RESET_TSF; ath9k_hw_reset_tsf(ah); } REG_SET_BIT(ah, AR_TIMER_MODE, flags); } +EXPORT_SYMBOL(ath9k_hw_beaconinit); void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, const struct ath9k_beacon_state *bs) { u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath_common *common = ath9k_hw_common(ah); REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); @@ -3518,10 +3082,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, else nextTbtt = bs->bs_nexttbtt; - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); + ath_print(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); + ath_print(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); + ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); + ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); REG_WRITE(ah, AR_NEXT_DTIM, TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); @@ -3549,6 +3113,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, /* TSF Out of Range Threshold */ REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); } +EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers); /*******************/ /* HW Capabilities */ @@ -3558,7 +3123,8 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) { struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; u16 capField = 0, eeval; @@ -3579,8 +3145,8 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) regulatory->current_rd += 5; else if (regulatory->current_rd == 0x41) regulatory->current_rd = 0x43; - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "regdomain mapped to 0x%x\n", regulatory->current_rd); + ath_print(common, ATH_DBG_REGULATORY, + "regdomain mapped to 0x%x\n", regulatory->current_rd); } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); @@ -3719,7 +3285,10 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; } - pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; + /* Advertise midband for AR5416 with FCC midband set in eeprom */ + if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && + AR_SREV_5416(ah)) + pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; pCap->num_antcfg_5ghz = ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); @@ -3727,18 +3296,18 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); if (AR_SREV_9280_10_OR_LATER(ah) && - ath_btcoex_supported(ah->hw_version.subsysid)) { - btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO; - btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO; + ath9k_hw_btcoex_supported(ah)) { + btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; + btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; if (AR_SREV_9285(ah)) { - btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_info->btpriority_gpio = ATH_BTPRIORITY_GPIO; + btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; + btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; } else { - btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_2WIRE; + btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; } } else { - btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_NONE; + btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; } } @@ -3812,6 +3381,7 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, return false; } } +EXPORT_SYMBOL(ath9k_hw_getcapability); bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 setting, int *status) @@ -3845,6 +3415,7 @@ bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, return false; } } +EXPORT_SYMBOL(ath9k_hw_setcapability); /****************************/ /* GPIO / RFKILL / Antennae */ @@ -3882,7 +3453,7 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) { u32 gpio_shift; - ASSERT(gpio < ah->caps.num_gpio_pins); + BUG_ON(gpio >= ah->caps.num_gpio_pins); gpio_shift = gpio << 1; @@ -3891,6 +3462,7 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); } +EXPORT_SYMBOL(ath9k_hw_cfg_gpio_input); u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) { @@ -3909,6 +3481,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) else return MS_REG_READ(AR, gpio) != 0; } +EXPORT_SYMBOL(ath9k_hw_gpio_get); void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, u32 ah_signal_type) @@ -3924,22 +3497,26 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); } +EXPORT_SYMBOL(ath9k_hw_cfg_output); void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) { REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), AR_GPIO_BIT(gpio)); } +EXPORT_SYMBOL(ath9k_hw_set_gpio); u32 ath9k_hw_getdefantenna(struct ath_hw *ah) { return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; } +EXPORT_SYMBOL(ath9k_hw_getdefantenna); void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) { REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); } +EXPORT_SYMBOL(ath9k_hw_setantenna); bool ath9k_hw_setantennaswitch(struct ath_hw *ah, enum ath9k_ant_setting settings, @@ -4002,6 +3579,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah) return bits; } +EXPORT_SYMBOL(ath9k_hw_getrxfilter); void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) { @@ -4023,19 +3601,30 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) REG_WRITE(ah, AR_RXCFG, REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); } +EXPORT_SYMBOL(ath9k_hw_setrxfilter); bool ath9k_hw_phy_disable(struct ath_hw *ah) { - return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) + return false; + + ath9k_hw_init_pll(ah, NULL); + return true; } +EXPORT_SYMBOL(ath9k_hw_phy_disable); bool ath9k_hw_disable(struct ath_hw *ah) { if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return false; - return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD)) + return false; + + ath9k_hw_init_pll(ah, NULL); + return true; } +EXPORT_SYMBOL(ath9k_hw_disable); void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) { @@ -4052,35 +3641,36 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) min((u32) MAX_RATE_POWER, (u32) regulatory->power_limit)); } +EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) { - memcpy(ah->macaddr, mac, ETH_ALEN); + memcpy(ath9k_hw_common(ah)->macaddr, mac, ETH_ALEN); } +EXPORT_SYMBOL(ath9k_hw_setmac); void ath9k_hw_setopmode(struct ath_hw *ah) { ath9k_hw_set_operating_mode(ah, ah->opmode); } +EXPORT_SYMBOL(ath9k_hw_setopmode); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) { REG_WRITE(ah, AR_MCAST_FIL0, filter0); REG_WRITE(ah, AR_MCAST_FIL1, filter1); } +EXPORT_SYMBOL(ath9k_hw_setmcastfilter); -void ath9k_hw_setbssidmask(struct ath_softc *sc) +void ath9k_hw_write_associd(struct ath_hw *ah) { - REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); - REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); -} + struct ath_common *common = ath9k_hw_common(ah); -void ath9k_hw_write_associd(struct ath_softc *sc) -{ - REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); - REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | - ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); + REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(common->curbssid)); + REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(common->curbssid + 4) | + ((common->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); } +EXPORT_SYMBOL(ath9k_hw_write_associd); u64 ath9k_hw_gettsf64(struct ath_hw *ah) { @@ -4091,24 +3681,25 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah) return tsf; } +EXPORT_SYMBOL(ath9k_hw_gettsf64); void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) { REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); } +EXPORT_SYMBOL(ath9k_hw_settsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah) { - ath9k_ps_wakeup(ah->ah_sc); if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, AH_TSF_WRITE_TIMEOUT)) - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, + "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); - ath9k_ps_restore(ah->ah_sc); } +EXPORT_SYMBOL(ath9k_hw_reset_tsf); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) { @@ -4117,11 +3708,13 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) else ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; } +EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) { if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us); + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, + "bad slot time %u\n", us); ah->slottime = (u32) -1; return false; } else { @@ -4130,13 +3723,14 @@ bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) return true; } } +EXPORT_SYMBOL(ath9k_hw_setslottime); -void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode) +void ath9k_hw_set11nmac2040(struct ath_hw *ah) { + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; u32 macmode; - if (mode == ATH9K_HT_MACMODE_2040 && - !ah->config.cwm_ignore_extcca) + if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca) macmode = AR_2040_JOINED_RX_CLEAR; else macmode = 0; @@ -4193,6 +3787,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah) { return REG_READ(ah, AR_TSF_L32); } +EXPORT_SYMBOL(ath9k_hw_gettsf32); struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), @@ -4206,8 +3801,9 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); if (timer == NULL) { - printk(KERN_DEBUG "Failed to allocate memory" - "for hw timer[%d]\n", timer_index); + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "Failed to allocate memory" + "for hw timer[%d]\n", timer_index); return NULL; } @@ -4220,10 +3816,12 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, return timer; } +EXPORT_SYMBOL(ath_gen_timer_alloc); -void ath_gen_timer_start(struct ath_hw *ah, - struct ath_gen_timer *timer, - u32 timer_next, u32 timer_period) +void ath9k_hw_gen_timer_start(struct ath_hw *ah, + struct ath_gen_timer *timer, + u32 timer_next, + u32 timer_period) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; u32 tsf; @@ -4234,8 +3832,9 @@ void ath_gen_timer_start(struct ath_hw *ah, tsf = ath9k_hw_gettsf32(ah); - DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, "curent tsf %x period %x" - "timer_next %x\n", tsf, timer_period, timer_next); + ath_print(ath9k_hw_common(ah), ATH_DBG_HWTIMER, + "curent tsf %x period %x" + "timer_next %x\n", tsf, timer_period, timer_next); /* * Pull timer_next forward if the current TSF already passed it @@ -4258,15 +3857,10 @@ void ath_gen_timer_start(struct ath_hw *ah, REG_SET_BIT(ah, AR_IMR_S5, (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); - - if ((ah->ah_sc->imask & ATH9K_INT_GENTIMER) == 0) { - ath9k_hw_set_interrupts(ah, 0); - ah->ah_sc->imask |= ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, ah->ah_sc->imask); - } } +EXPORT_SYMBOL(ath9k_hw_gen_timer_start); -void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) +void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; @@ -4285,14 +3879,8 @@ void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); clear_bit(timer->index, &timer_table->timer_mask.timer_bits); - - /* if no timer is enabled, turn off interrupt mask */ - if (timer_table->timer_mask.val == 0) { - ath9k_hw_set_interrupts(ah, 0); - ah->ah_sc->imask &= ~ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, ah->ah_sc->imask); - } } +EXPORT_SYMBOL(ath9k_hw_gen_timer_stop); void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) { @@ -4302,6 +3890,7 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) timer_table->timers[timer->index] = NULL; kfree(timer); } +EXPORT_SYMBOL(ath_gen_timer_free); /* * Generic Timer Interrupts handling @@ -4310,6 +3899,7 @@ void ath_gen_timer_isr(struct ath_hw *ah) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; struct ath_gen_timer *timer; + struct ath_common *common = ath9k_hw_common(ah); u32 trigger_mask, thresh_mask, index; /* get hardware generic timer interrupt status */ @@ -4324,8 +3914,8 @@ void ath_gen_timer_isr(struct ath_hw *ah) index = rightmost_index(timer_table, &thresh_mask); timer = timer_table->timers[index]; BUG_ON(!timer); - DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, - "TSF overflow for Gen timer %d\n", index); + ath_print(common, ATH_DBG_HWTIMER, + "TSF overflow for Gen timer %d\n", index); timer->overflow(timer->arg); } @@ -4333,21 +3923,95 @@ void ath_gen_timer_isr(struct ath_hw *ah) index = rightmost_index(timer_table, &trigger_mask); timer = timer_table->timers[index]; BUG_ON(!timer); - DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, - "Gen timer[%d] trigger\n", index); + ath_print(common, ATH_DBG_HWTIMER, + "Gen timer[%d] trigger\n", index); timer->trigger(timer->arg); } } +EXPORT_SYMBOL(ath_gen_timer_isr); + +static struct { + u32 version; + const char * name; +} ath_mac_bb_names[] = { + /* Devices with external radios */ + { AR_SREV_VERSION_5416_PCI, "5416" }, + { AR_SREV_VERSION_5416_PCIE, "5418" }, + { AR_SREV_VERSION_9100, "9100" }, + { AR_SREV_VERSION_9160, "9160" }, + /* Single-chip solutions */ + { AR_SREV_VERSION_9280, "9280" }, + { AR_SREV_VERSION_9285, "9285" }, + { AR_SREV_VERSION_9287, "9287" }, + { AR_SREV_VERSION_9271, "9271" }, +}; + +/* For devices with external radios */ +static struct { + u16 version; + const char * name; +} ath_rf_names[] = { + { 0, "5133" }, + { AR_RAD5133_SREV_MAJOR, "5133" }, + { AR_RAD5122_SREV_MAJOR, "5122" }, + { AR_RAD2133_SREV_MAJOR, "2133" }, + { AR_RAD2122_SREV_MAJOR, "2122" } +}; /* - * Primitive to disable ASPM + * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. */ -void ath_pcie_aspm_disable(struct ath_softc *sc) +static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version) { - struct pci_dev *pdev = to_pci_dev(sc->dev); - u8 aspm; + int i; + + for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) { + if (ath_mac_bb_names[i].version == mac_bb_version) { + return ath_mac_bb_names[i].name; + } + } + + return "????"; +} + +/* + * Return the RF name. "????" is returned if the RF is unknown. + * Used for devices with external radios. + */ +static const char *ath9k_hw_rf_name(u16 rf_version) +{ + int i; + + for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) { + if (ath_rf_names[i].version == rf_version) { + return ath_rf_names[i].name; + } + } + + return "????"; +} + +void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) +{ + int used; + + /* chipsets >= AR9280 are single-chip */ + if (AR_SREV_9280_10_OR_LATER(ah)) { + used = snprintf(hw_name, len, + "Atheros AR%s Rev:%x", + ath9k_hw_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev); + } + else { + used = snprintf(hw_name, len, + "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", + ath9k_hw_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev, + ath9k_hw_rf_name((ah->hw_version.analog5GhzRev & + AR_RADIO_SREV_MAJOR)), + ah->hw_version.phyRev); + } - 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); + hw_name[used] = '\0'; } +EXPORT_SYMBOL(ath9k_hw_name); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b892345..c7b0c4d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -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 @@ -132,6 +148,15 @@ enum wireless_mode { ATH9K_MODE_MAX, }; +/** + * ath9k_ant_setting - transmit antenna settings + * + * Configures the antenna setting to use for transmit. + * + * @ATH9K_ANT_VARIABLE: this means transmit on all active antennas + * @ATH9K_ANT_FIXED_A: this means transmit on the first antenna only + * @ATH9K_ANT_FIXED_B: this means transmit on the second antenna only + */ enum ath9k_ant_setting { ATH9K_ANT_VARIABLE = 0, ATH9K_ANT_FIXED_A, @@ -433,7 +458,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 +476,6 @@ struct ath_hw { bool sw_mgmt_crypto; bool is_pciexpress; - u8 macaddr[ETH_ALEN]; u16 tx_trig_level; u16 rfsilent; u32 rfkill_gpio; @@ -523,7 +548,14 @@ struct ath_hw { DONT_USE_32KHZ, } enable_32kHz_clock; - /* RF */ + /* Callback for radio frequency change */ + int (*ath9k_hw_rf_set_freq)(struct ath_hw *ah, struct ath9k_channel *chan); + + /* Callback for baseband spur frequency */ + void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah, + struct ath9k_channel *chan); + + /* Used to program the radio on non single-chip devices */ u32 *analogBank0Data; u32 *analogBank1Data; u32 *analogBank2Data; @@ -553,8 +585,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,17 +612,29 @@ struct ath_hw { struct ar5416IniArray iniModesAdditional; struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesTxGain; + struct ar5416IniArray iniModes_9271_1_0_only; + 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); int ath9k_hw_init(struct ath_hw *ah); -void ath9k_hw_rf_free(struct ath_hw *ah); int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange); void ath9k_hw_fill_cap_info(struct ath_hw *ah); @@ -637,19 +683,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,16 +710,20 @@ 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); +void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); + #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 -void ath_pcie_aspm_disable(struct ath_softc *sc); #endif diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index 8622265..8a3bf3a 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h @@ -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 }, @@ -6365,8 +6379,8 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { }; -/* AR9271 initialization values automaticaly created: 03/23/09 */ -static const u_int32_t ar9271Modes_9271_1_0[][6] = { +/* AR9271 initialization values automaticaly created: 06/04/09 */ +static const u_int32_t ar9271Modes_9271[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -6376,8 +6390,8 @@ static const u_int32_t ar9271Modes_9271_1_0[][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 }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, + { 0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001 }, { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, @@ -6391,6 +6405,7 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = { { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310 }, { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, @@ -6401,7 +6416,7 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = { { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, + { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, @@ -6690,7 +6705,7 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = { { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; -static const u_int32_t ar9271Common_9271_1_0[][2] = { +static const u_int32_t ar9271Common_9271[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020045 }, { 0x00000034, 0x00000005 }, @@ -6786,7 +6801,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x0000803c, 0x00000000 }, { 0x00008048, 0x00000000 }, { 0x00008054, 0x00000000 }, - { 0x00008058, 0x02000000 }, + { 0x00008058, 0x00000000 }, { 0x0000805c, 0x000fc78f }, { 0x00008060, 0x0000000f }, { 0x00008064, 0x00000000 }, @@ -6817,7 +6832,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x00008110, 0x00000168 }, { 0x00008118, 0x000100aa }, { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04814 }, + { 0x00008120, 0x08f04810 }, { 0x00008124, 0x00000000 }, { 0x00008128, 0x00000000 }, { 0x0000812c, 0x00000000 }, @@ -6864,7 +6879,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, + { 0x00008264, 0x88a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -6896,7 +6911,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x00007814, 0x924934a8 }, { 0x0000781c, 0x00000000 }, { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d86bff }, + { 0x00007824, 0x00d8abff }, { 0x00007828, 0x66964300 }, { 0x0000782c, 0x8db6d961 }, { 0x00007830, 0x8db6d96c }, @@ -6930,7 +6945,6 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x00009904, 0x00000000 }, { 0x00009908, 0x00000000 }, { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x30002310 }, { 0x0000991c, 0x10000fff }, { 0x00009920, 0x04900000 }, { 0x00009928, 0x00000001 }, @@ -6944,7 +6958,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x00009954, 0x5f3ca3de }, { 0x00009958, 0x0108ecff }, { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb515 }, + { 0x00009970, 0x192bb514 }, { 0x00009974, 0x00000000 }, { 0x00009978, 0x00000001 }, { 0x0000997c, 0x00000000 }, @@ -7031,3 +7045,8 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x0000d380, 0x7f3c7bba }, { 0x0000d384, 0xf3307ff0 }, }; + +static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { + { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, +}; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 800bfab..46466ff 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index f56e77d..fefb65d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -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 */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 52bed89..9fefc51 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -16,6 +16,7 @@ #include <linux/nl80211.h> #include "ath9k.h" +#include "btcoex.h" static char *dev_info = "ath9k"; @@ -28,6 +29,10 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); +static unsigned int ath9k_debug = ATH_DBG_DEFAULT; +module_param_named(debug, ath9k_debug, uint, 0); +MODULE_PARM_DESC(debug, "Debugging mask"); + /* We use the hw_value as an index into our private channel structure */ #define CHAN2G(_freq, _idx) { \ @@ -224,8 +229,9 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) } sband->n_bitrates++; - DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n", - rate[i].bitrate / 10, rate[i].hw_value); + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, + "Rate: %2dMbps, ratecode: %2d\n", + rate[i].bitrate / 10, rate[i].hw_value); } } @@ -242,6 +248,51 @@ static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, return channel; } +static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&sc->sc_pm_lock, flags); + ret = ath9k_hw_setpower(sc->sc_ah, mode); + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); + + return ret; +} + +void ath9k_ps_wakeup(struct ath_softc *sc) +{ + unsigned long flags; + + spin_lock_irqsave(&sc->sc_pm_lock, flags); + if (++sc->ps_usecount != 1) + goto unlock; + + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + + unlock: + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); +} + +void ath9k_ps_restore(struct ath_softc *sc) +{ + unsigned long flags; + + spin_lock_irqsave(&sc->sc_pm_lock, flags); + if (--sc->ps_usecount != 0) + goto unlock; + + if (sc->ps_enabled && + !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | + SC_OP_WAIT_FOR_CAB | + SC_OP_WAIT_FOR_PSPOLL_DATA | + SC_OP_WAIT_FOR_TX_ACK))) + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); + + unlock: + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); +} + /* * Set/change channels. If the channel is really being changed, it's done * by reseting the chip. To accomplish this we must first cleanup any pending @@ -251,6 +302,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, struct ath9k_channel *hchan) { struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_conf *conf = &common->hw->conf; bool fastcc = true, stopped; struct ieee80211_channel *channel = hw->conf.channel; int r; @@ -280,19 +333,19 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) fastcc = false; - DPRINTF(sc, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), chanwidth: %d\n", - sc->sc_ah->curchan->channel, - channel->center_freq, sc->tx_chan_width); + ath_print(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", + sc->sc_ah->curchan->channel, + channel->center_freq, conf_is_ht40(conf)); spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, hchan, fastcc); if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %d\n", - channel->center_freq, r); + ath_print(common, ATH_DBG_FATAL, + "Unable to reset channel (%u Mhz) " + "reset status %d\n", + channel->center_freq, r); spin_unlock_bh(&sc->sc_resetlock); goto ps_restore; } @@ -301,8 +354,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, sc->sc_flags &= ~SC_OP_FULL_RESET; if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to restart recv logic\n"); r = -EIO; goto ps_restore; } @@ -327,6 +380,7 @@ static void ath_ani_calibrate(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); bool longcal = false; bool shortcal = false; bool aniflag = false; @@ -353,7 +407,7 @@ static void ath_ani_calibrate(unsigned long data) /* Long calibration runs independently of short calibration. */ if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { longcal = true; - DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); sc->ani.longcal_timer = timestamp; } @@ -361,7 +415,8 @@ static void ath_ani_calibrate(unsigned long data) if (!sc->ani.caldone) { if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; - DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies); + ath_print(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); sc->ani.shortcal_timer = timestamp; sc->ani.resetcal_timer = timestamp; } @@ -388,16 +443,21 @@ static void ath_ani_calibrate(unsigned long data) /* Perform calibration if necessary */ if (longcal || shortcal) { - sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, - sc->rx_chainmask, longcal); + sc->ani.caldone = + ath9k_hw_calibrate(ah, + ah->curchan, + common->rx_chainmask, + longcal); if (longcal) sc->ani.noise_floor = ath9k_hw_getchan_noise(ah, ah->curchan); - DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n", - ah->curchan->channel, ah->curchan->channelFlags, - sc->ani.noise_floor); + ath_print(common, ATH_DBG_ANI, + " calibrate chan %u/%x nf: %d\n", + ah->curchan->channel, + ah->curchan->channelFlags, + sc->ani.noise_floor); } } @@ -439,17 +499,22 @@ static void ath_start_ani(struct ath_softc *sc) */ void ath_update_chainmask(struct ath_softc *sc, int is_ht) { + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || - (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE)) { - sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; - sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask; + (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { + common->tx_chainmask = ah->caps.tx_chainmask; + common->rx_chainmask = ah->caps.rx_chainmask; } else { - sc->tx_chainmask = 1; - sc->rx_chainmask = 1; + common->tx_chainmask = 1; + common->rx_chainmask = 1; } - DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n", - sc->tx_chainmask, sc->rx_chainmask); + ath_print(common, ATH_DBG_CONFIG, + "tx chmask: %d, rx chmask: %d\n", + common->tx_chainmask, + common->rx_chainmask); } static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) @@ -478,6 +543,9 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) static void ath9k_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); + u32 status = sc->intrstatus; ath9k_ps_wakeup(sc); @@ -502,16 +570,17 @@ static void ath9k_tasklet(unsigned long data) * TSF sync does not look correct; remain awake to sync with * the next Beacon. */ - DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); + ath_print(common, ATH_DBG_PS, + "TSFOOR - Sync with next Beacon\n"); sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; } - if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) + if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) if (status & ATH9K_INT_GENTIMER) ath_gen_timer_isr(sc->sc_ah); /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, sc->imask); ath9k_ps_restore(sc); } @@ -602,7 +671,7 @@ irqreturn_t ath_isr(int irq, void *dev) if (status & ATH9K_INT_TIM_TIMER) { /* Clear RxAbort bit so that we can * receive frames */ - ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); + ath9k_setpower(sc, ATH9K_PM_AWAKE); ath9k_hw_setrxabort(sc->sc_ah, 0); sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; } @@ -702,8 +771,8 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { /* TX MIC entry failed. No need to proceed further */ - DPRINTF(sc, ATH_DBG_FATAL, - "Setting TX MIC Key Failed\n"); + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, + "Setting TX MIC Key Failed\n"); return 0; } @@ -890,6 +959,7 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) static void setup_ht_cap(struct ath_softc *sc, struct ieee80211_sta_ht_cap *ht_info) { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); u8 tx_streams, rx_streams; ht_info->ht_supported = true; @@ -903,12 +973,15 @@ static void setup_ht_cap(struct ath_softc *sc, /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - tx_streams = !(sc->tx_chainmask & (sc->tx_chainmask - 1)) ? 1 : 2; - rx_streams = !(sc->rx_chainmask & (sc->rx_chainmask - 1)) ? 1 : 2; + tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? + 1 : 2; + rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? + 1 : 2; if (tx_streams != rx_streams) { - DPRINTF(sc, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); + ath_print(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; ht_info->mcs.tx_params |= ((tx_streams - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); @@ -925,14 +998,17 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) { + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); if (bss_conf->assoc) { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, sc->curbssid); + ath_print(common, ATH_DBG_CONFIG, + "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, common->curbssid); /* New association, store aid */ - sc->curaid = bss_conf->aid; - ath9k_hw_write_associd(sc); + common->curaid = bss_conf->aid; + ath9k_hw_write_associd(ah); /* * Request a re-configuration of Beacon related timers @@ -949,8 +1025,8 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ath_start_ani(sc); } else { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); - sc->curaid = 0; + ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); + common->curaid = 0; /* Stop ANI */ del_timer_sync(&sc->ani.timer); } @@ -1042,8 +1118,8 @@ static int ath_register_led(struct ath_softc *sc, struct ath_led *led, ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); if (ret) - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to register led:%s", led->name); + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, + "Failed to register led:%s", led->name); else led->registered = 1; return ret; @@ -1127,6 +1203,7 @@ fail: void ath_radio_enable(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *channel = sc->hw->conf.channel; int r; @@ -1139,17 +1216,17 @@ void ath_radio_enable(struct ath_softc *sc) spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, false); if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) ", - "reset status %d\n", - channel->center_freq, r); + ath_print(common, ATH_DBG_FATAL, + "Unable to reset channel %u (%uMhz) ", + "reset status %d\n", + channel->center_freq, r); } spin_unlock_bh(&sc->sc_resetlock); ath_update_txpow(sc); if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to restart recv logic\n"); return; } @@ -1194,17 +1271,17 @@ void ath_radio_disable(struct ath_softc *sc) spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, false); if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) " - "reset status %d\n", - channel->center_freq, r); + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, + "Unable to reset channel %u (%uMhz) " + "reset status %d\n", + channel->center_freq, r); } spin_unlock_bh(&sc->sc_resetlock); ath9k_hw_phy_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); ath9k_ps_restore(sc); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } /*******************/ @@ -1236,23 +1313,26 @@ static void ath_start_rfkill_poll(struct ath_softc *sc) wiphy_rfkill_start_polling(sc->hw->wiphy); } -void ath_cleanup(struct ath_softc *sc) +static void ath9k_uninit_hw(struct ath_softc *sc) { - ath_detach(sc); - free_irq(sc->irq, sc); - ath_bus_cleanup(sc); - kfree(sc->sec_wiphy); - ieee80211_free_hw(sc->hw); + struct ath_hw *ah = sc->sc_ah; + + BUG_ON(!ah); + + ath9k_exit_debug(ah); + ath9k_hw_detach(ah); + sc->sc_ah = NULL; } -void ath_detach(struct ath_softc *sc) +static void ath_clean_core(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; + struct ath_hw *ah = sc->sc_ah; int i = 0; ath9k_ps_wakeup(sc); - DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); + dev_dbg(sc->dev, "Detach ATH hw\n"); ath_deinit_leds(sc); wiphy_rfkill_stop_polling(sc->hw->wiphy); @@ -1273,20 +1353,36 @@ void ath_detach(struct ath_softc *sc) tasklet_kill(&sc->bcon_tasklet); if (!(sc->sc_flags & SC_OP_INVALID)) - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + ath9k_setpower(sc, ATH9K_PM_AWAKE); /* cleanup tx queues */ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); - if ((sc->btcoex_info.no_stomp_timer) && - sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - ath_gen_timer_free(sc->sc_ah, sc->btcoex_info.no_stomp_timer); + if ((sc->btcoex.no_stomp_timer) && + ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) + ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); +} - ath9k_hw_detach(sc->sc_ah); - sc->sc_ah = NULL; - ath9k_exit_debug(sc); +void ath_detach(struct ath_softc *sc) +{ + ath_clean_core(sc); + ath9k_uninit_hw(sc); +} + +void ath_cleanup(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + + ath_clean_core(sc); + free_irq(sc->irq, sc); + ath_bus_cleanup(common); + kfree(sc->sec_wiphy); + ieee80211_free_hw(sc->hw); + + ath9k_uninit_hw(sc); } static int ath9k_reg_notifier(struct wiphy *wiphy, @@ -1295,29 +1391,245 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_regulatory *reg = &sc->common.regulatory; + struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); return ath_reg_notifier_apply(wiphy, request, reg); } /* + * Detects if there is any priority bt traffic + */ +static void ath_detect_bt_priority(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_hw *ah = sc->sc_ah; + + if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio)) + btcoex->bt_priority_cnt++; + + if (time_after(jiffies, btcoex->bt_priority_time + + msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { + if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, + "BT priority traffic detected"); + sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; + } else { + sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; + } + + btcoex->bt_priority_cnt = 0; + btcoex->bt_priority_time = jiffies; + } +} + +/* + * Configures appropriate weight based on stomp type. + */ +static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, + enum ath_stomp_type stomp_type) +{ + struct ath_hw *ah = sc->sc_ah; + + switch (stomp_type) { + case ATH_BTCOEX_STOMP_ALL: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_ALL_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_LOW: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_NONE: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_NONE_WLAN_WGHT); + break; + default: + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); + break; + } + + ath9k_hw_btcoex_enable(ah); +} + +static void ath9k_gen_timer_start(struct ath_hw *ah, + struct ath_gen_timer *timer, + u32 timer_next, + u32 timer_period) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + + ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); + + if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { + ath9k_hw_set_interrupts(ah, 0); + sc->imask |= ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah, sc->imask); + } +} + +static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; + + ath9k_hw_gen_timer_stop(ah, timer); + + /* if no timer is enabled, turn off interrupt mask */ + if (timer_table->timer_mask.val == 0) { + ath9k_hw_set_interrupts(ah, 0); + sc->imask &= ~ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah, sc->imask); + } +} + +/* + * 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_hw *ah = sc->sc_ah; + struct ath_btcoex *btcoex = &sc->btcoex; + + ath_detect_bt_priority(sc); + + spin_lock_bh(&btcoex->btcoex_lock); + + ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); + + spin_unlock_bh(&btcoex->btcoex_lock); + + if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); + + ath9k_gen_timer_start(ah, + btcoex->no_stomp_timer, + (ath9k_hw_gettsf32(ah) + + btcoex->btcoex_no_stomp), + btcoex->btcoex_no_stomp * 10); + btcoex->hw_timer_enabled = true; + } + + mod_timer(&btcoex->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_hw *ah = sc->sc_ah; + struct ath_btcoex *btcoex = &sc->btcoex; + + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "no stomp timer running \n"); + + spin_lock_bh(&btcoex->btcoex_lock); + + if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) + ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); + else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) + ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); + + spin_unlock_bh(&btcoex->btcoex_lock); +} + +static int ath_init_btcoex_timer(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + + btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; + btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * + btcoex->btcoex_period / 100; + + setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, + (unsigned long) sc); + + spin_lock_init(&btcoex->btcoex_lock); + + btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, + ath_btcoex_no_stomp_timer, + ath_btcoex_no_stomp_timer, + (void *) sc, AR_FIRST_NDP_TIMER); + + if (!btcoex->no_stomp_timer) + return -ENOMEM; + + return 0; +} + +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&sc->sc_serial_rw, flags); + iowrite32(val, sc->mem + reg_offset); + spin_unlock_irqrestore(&sc->sc_serial_rw, flags); + } else + iowrite32(val, sc->mem + reg_offset); +} + +static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + u32 val; + + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&sc->sc_serial_rw, flags); + val = ioread32(sc->mem + reg_offset); + spin_unlock_irqrestore(&sc->sc_serial_rw, flags); + } else + val = ioread32(sc->mem + reg_offset); + return val; +} + +static const struct ath_ops ath9k_common_ops = { + .read = ath9k_ioread32, + .write = ath9k_iowrite32, +}; + +/* * Initialize and fill ath_softc, ath_sofct is the * "Software Carrier" struct. Historically it has existed * to allow the separation between hardware specific * variables (now in ath_hw) and driver specific variables. */ -static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) +static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, + const struct ath_bus_ops *bus_ops) { struct ath_hw *ah = NULL; + struct ath_common *common; int r = 0, i; int csz = 0; + int qnum; /* XXX: hardware will not be ready until ath_open() being called */ sc->sc_flags |= SC_OP_INVALID; - if (ath9k_init_debug(sc) < 0) - printk(KERN_ERR "Unable to create debugfs files\n"); - spin_lock_init(&sc->wiphy_lock); spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); @@ -1328,39 +1640,50 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, (unsigned long)sc); - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - ath_read_cachesize(sc, &csz); - /* XXX assert csz is non-zero */ - sc->common.cachelsz = csz << 2; /* convert to bytes */ - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); - if (!ah) { - r = -ENOMEM; - goto bad_no_ah; - } + if (!ah) + return -ENOMEM; - ah->ah_sc = sc; ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; + common = ath9k_hw_common(ah); + common->ops = &ath9k_common_ops; + common->bus_ops = bus_ops; + common->ah = ah; + common->hw = sc->hw; + common->priv = sc; + common->debug_mask = ath9k_debug; + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath_read_cachesize(common, &csz); + /* XXX assert csz is non-zero */ + common->cachelsz = csz << 2; /* convert to bytes */ + r = ath9k_hw_init(ah); if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", r); - goto bad; + ath_print(common, ATH_DBG_FATAL, + "Unable to initialize hardware; " + "initialization status: %d\n", r); + goto bad_free_hw; + } + + if (ath9k_init_debug(ah) < 0) { + ath_print(common, ATH_DBG_FATAL, + "Unable to create debugfs files\n"); + goto bad_free_hw; } /* Get the hardware key cache size. */ sc->keymax = ah->caps.keycache_size; if (sc->keymax > ATH_KEYMAX) { - DPRINTF(sc, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, sc->keymax); + ath_print(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, sc->keymax); sc->keymax = ATH_KEYMAX; } @@ -1386,17 +1709,17 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) * priority. Note that the hal handles reseting * these queues at the needed time. */ - sc->beacon.beaconq = ath_beaconq_setup(ah); + sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); if (sc->beacon.beaconq == -1) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup a beacon xmit queue\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to setup a beacon xmit queue\n"); r = -EIO; goto bad2; } sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); if (sc->beacon.cabq == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to setup CAB xmit queue\n"); r = -EIO; goto bad2; } @@ -1410,27 +1733,27 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) /* Setup data queues */ /* NB: ensure BK queue is the lowest priority h/w queue */ if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for BK traffic\n"); r = -EIO; goto bad2; } if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for BE traffic\n"); r = -EIO; goto bad2; } if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for VI traffic\n"); r = -EIO; goto bad2; } if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for VO traffic\n"); r = -EIO; goto bad2; } @@ -1480,14 +1803,14 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) sc->sc_flags |= SC_OP_RXAGGR; } - sc->tx_chainmask = ah->caps.tx_chainmask; - sc->rx_chainmask = ah->caps.rx_chainmask; + common->tx_chainmask = ah->caps.tx_chainmask; + common->rx_chainmask = ah->caps.rx_chainmask; ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); sc->rx.defant = ath9k_hw_getdefantenna(ah); if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); + memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ @@ -1515,10 +1838,24 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) ARRAY_SIZE(ath9k_5ghz_chantable); } - if (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) { - r = ath9k_hw_btcoex_init(ah); + switch (ah->btcoex_hw.scheme) { + case ATH_BTCOEX_CFG_NONE: + break; + case ATH_BTCOEX_CFG_2WIRE: + ath9k_hw_btcoex_init_2wire(ah); + break; + case ATH_BTCOEX_CFG_3WIRE: + ath9k_hw_btcoex_init_3wire(ah); + r = ath_init_btcoex_timer(sc); if (r) goto bad2; + qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); + ath9k_hw_init_btcoex_hw(ah, qnum); + sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; + break; + default: + WARN_ON(1); + break; } return 0; @@ -1527,12 +1864,9 @@ bad2: for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); -bad: - ath9k_hw_detach(ah); - sc->sc_ah = NULL; -bad_no_ah: - ath9k_exit_debug(sc); +bad_free_hw: + ath9k_uninit_hw(sc); return r; } @@ -1574,34 +1908,40 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) } /* Device driver core initialization */ -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) { struct ieee80211_hw *hw = sc->hw; + struct ath_common *common; + struct ath_hw *ah; int error = 0, i; struct ath_regulatory *reg; - DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); + dev_dbg(sc->dev, "Attach ATH hw\n"); - error = ath_init_softc(devid, sc, subsysid); + error = ath_init_softc(devid, sc, subsysid, bus_ops); if (error != 0) return error; + ah = sc->sc_ah; + common = ath9k_hw_common(ah); + /* get mac address from hardware and set in mac80211 */ - SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); ath_set_hw_capab(sc, hw); - error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy, + error = ath_regd_init(&common->regulatory, sc->hw->wiphy, ath9k_reg_notifier); if (error) return error; - reg = &sc->common.regulatory; + reg = &common->regulatory; - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); } @@ -1639,9 +1979,7 @@ error_attach: if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); - ath9k_hw_detach(sc->sc_ah); - sc->sc_ah = NULL; - ath9k_exit_debug(sc); + ath9k_uninit_hw(sc); return error; } @@ -1649,6 +1987,7 @@ error_attach: int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_hw *hw = sc->hw; int r; @@ -1660,12 +1999,13 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); 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); if (ath_startrecv(sc) != 0) - DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to start recv logic\n"); /* * We may be doing a reset in response to a request @@ -1708,19 +2048,20 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) - + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_desc *ds; struct ath_buf *bf; int i, bsize, error; - DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", - name, nbuf, ndesc); + ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", + name, nbuf, ndesc); INIT_LIST_HEAD(head); /* ath_desc must be a multiple of DWORDs */ if ((sizeof(struct ath_desc) % 4) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); - ASSERT((sizeof(struct ath_desc) % 4) == 0); + ath_print(common, ATH_DBG_FATAL, + "ath_desc not DWORD aligned\n"); + BUG_ON((sizeof(struct ath_desc) % 4) != 0); error = -ENOMEM; goto fail; } @@ -1753,9 +2094,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, goto fail; } ds = dd->dd_desc; - DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - name, ds, (u32) dd->dd_desc_len, - ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); + ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", + name, ds, (u32) dd->dd_desc_len, + ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); /* allocate buffers */ bsize = sizeof(struct ath_buf) * nbuf; @@ -1778,7 +2119,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, * descriptor fetch. */ while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { - ASSERT((caddr_t) bf->bf_desc < + BUG_ON((caddr_t) bf->bf_desc >= ((caddr_t) dd->dd_desc + dd->dd_desc_len)); @@ -1882,31 +2223,50 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; } - sc->tx_chan_width = ATH9K_HT_MACMODE_20; - - if (conf_is_ht(conf)) { - if (conf_is_ht40(conf)) - sc->tx_chan_width = ATH9K_HT_MACMODE_2040; - + if (conf_is_ht(conf)) ichan->chanmode = ath_get_extchanmode(sc, chan, conf->channel_type); - } } /**********************/ /* mac80211 callbacks */ /**********************/ +/* + * (Re)start btcoex timers + */ +static void ath9k_btcoex_timer_resume(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_hw *ah = sc->sc_ah; + + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Starting btcoex timers"); + + /* make sure duty cycle timer is also stopped when resuming */ + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); + + btcoex->bt_priority_cnt = 0; + btcoex->bt_priority_time = jiffies; + sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; + + mod_timer(&btcoex->period_timer, jiffies); +} + static int ath9k_start(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *curchan = hw->conf.channel; struct ath9k_channel *init_channel; int r; - DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " - "initial channel: %d MHz\n", curchan->center_freq); + ath_print(common, ATH_DBG_CONFIG, + "Starting driver with initial channel: %d MHz\n", + curchan->center_freq); mutex_lock(&sc->mutex); @@ -1938,7 +2298,7 @@ static int ath9k_start(struct ieee80211_hw *hw) init_channel = ath_get_curchannel(sc, hw); /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0); + ath9k_hw_configpcipowersave(ah, 0, 0); /* * The basic interface to setting the hardware in a good @@ -1948,12 +2308,12 @@ static int ath9k_start(struct ieee80211_hw *hw) * and then setup of the interrupt mask. */ spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(sc->sc_ah, init_channel, false); + r = ath9k_hw_reset(ah, init_channel, false); if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", r, - curchan->center_freq); + ath_print(common, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %d " + "(freq %u MHz)\n", r, + curchan->center_freq); spin_unlock_bh(&sc->sc_resetlock); goto mutex_unlock; } @@ -1973,7 +2333,8 @@ static int ath9k_start(struct ieee80211_hw *hw) * here except setup the interrupt mask. */ if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to start recv logic\n"); r = -EIO; goto mutex_unlock; } @@ -1983,10 +2344,10 @@ static int ath9k_start(struct ieee80211_hw *hw) | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT) + if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) sc->imask |= ATH9K_INT_GTT; - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) + if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) sc->imask |= ATH9K_INT_CST; ath_cache_conf_rate(sc, &hw->conf); @@ -1995,21 +2356,22 @@ static int ath9k_start(struct ieee80211_hw *hw) /* Disable BMISS interrupt when we're not associated */ sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_hw_set_interrupts(ah, sc->imask); ieee80211_wake_queues(hw); ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); - if ((sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) && - !(sc->sc_flags & SC_OP_BTCOEX_ENABLED)) { - ath_btcoex_set_weight(&sc->btcoex_info, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - ath9k_hw_btcoex_enable(sc->sc_ah); + if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && + !ah->btcoex_hw.enabled) { + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + ath9k_hw_btcoex_enable(ah); - ath_pcie_aspm_disable(sc); - if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - ath_btcoex_timer_resume(sc, &sc->btcoex_info); + if (common->bus_ops->bt_coex_prep) + common->bus_ops->bt_coex_prep(common); + if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) + ath9k_btcoex_timer_resume(sc); } mutex_unlock: @@ -2024,12 +2386,14 @@ static int ath9k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(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_tx_control txctl; int hdrlen, padsize; if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { - printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " - "%d\n", wiphy_name(hw->wiphy), aphy->state); + ath_print(common, ATH_DBG_XMIT, + "ath9k: %s: TX in unexpected wiphy state " + "%d\n", wiphy_name(hw->wiphy), aphy->state); goto exit; } @@ -2042,8 +2406,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, if (ieee80211_is_data(hdr->frame_control) && !ieee80211_is_nullfunc(hdr->frame_control) && !ieee80211_has_pm(hdr->frame_control)) { - DPRINTF(sc, ATH_DBG_PS, "Add PM=1 for a TX frame " - "while in PS mode\n"); + ath_print(common, ATH_DBG_PS, "Add PM=1 for a TX frame " + "while in PS mode\n"); hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); } } @@ -2058,11 +2422,12 @@ static int ath9k_tx(struct ieee80211_hw *hw, ath9k_ps_wakeup(sc); ath9k_hw_setrxabort(sc->sc_ah, 0); if (ieee80211_is_pspoll(hdr->frame_control)) { - DPRINTF(sc, ATH_DBG_PS, "Sending PS-Poll to pick a " - "buffered frame\n"); + ath_print(common, ATH_DBG_PS, + "Sending PS-Poll to pick a buffered frame\n"); sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; } else { - DPRINTF(sc, ATH_DBG_PS, "Wake up to complete TX\n"); + ath_print(common, ATH_DBG_PS, + "Wake up to complete TX\n"); sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; } /* @@ -2104,10 +2469,10 @@ static int ath9k_tx(struct ieee80211_hw *hw, if (!txctl.txq) goto exit; - DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); + ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); if (ath_tx_start(hw, skb, &txctl) != 0) { - DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n"); + ath_print(common, ATH_DBG_XMIT, "TX failed\n"); goto exit; } @@ -2117,10 +2482,28 @@ exit: return 0; } +/* + * Pause btcoex timer and bt duty cycle timer + */ +static void ath9k_btcoex_timer_pause(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_hw *ah = sc->sc_ah; + + del_timer_sync(&btcoex->period_timer); + + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); + + btcoex->hw_timer_enabled = false; +} + static void ath9k_stop(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); mutex_lock(&sc->mutex); @@ -2135,7 +2518,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) } if (sc->sc_flags & SC_OP_INVALID) { - DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); + ath_print(common, ATH_DBG_ANY, "Device not present\n"); mutex_unlock(&sc->mutex); return; } @@ -2145,33 +2528,33 @@ static void ath9k_stop(struct ieee80211_hw *hw) return; /* another wiphy still in use */ } - if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { - ath9k_hw_btcoex_disable(sc->sc_ah); - if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - ath_btcoex_timer_pause(sc, &sc->btcoex_info); + if (ah->btcoex_hw.enabled) { + ath9k_hw_btcoex_disable(ah); + if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) + ath9k_btcoex_timer_pause(sc); } /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_set_interrupts(ah, 0); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_drain_all_txq(sc, false); ath_stoprecv(sc); - ath9k_hw_phy_disable(sc->sc_ah); + ath9k_hw_phy_disable(ah); } else sc->rx.rxlink = NULL; /* disable HAL and put h/w to sleep */ - ath9k_hw_disable(sc->sc_ah); - ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); + ath9k_hw_disable(ah); + ath9k_hw_configpcipowersave(ah, 1, 1); + ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); sc->sc_flags |= SC_OP_INVALID; mutex_unlock(&sc->mutex); - DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n"); + ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); } static int ath9k_add_interface(struct ieee80211_hw *hw, @@ -2179,6 +2562,7 @@ static int ath9k_add_interface(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_vif *avp = (void *)conf->vif->drv_priv; enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; int ret = 0; @@ -2205,13 +2589,14 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ic_opmode = conf->type; break; default: - DPRINTF(sc, ATH_DBG_FATAL, + ath_print(common, ATH_DBG_FATAL, "Interface type %d not yet supported\n", conf->type); ret = -EOPNOTSUPP; goto out; } - DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); + ath_print(common, ATH_DBG_CONFIG, + "Attach a VIF of type: %d\n", ic_opmode); /* Set the VIF opmode */ avp->av_opmode = ic_opmode; @@ -2261,10 +2646,11 @@ static void ath9k_remove_interface(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_vif *avp = (void *)conf->vif->drv_priv; int i; - DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); + ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); mutex_lock(&sc->mutex); @@ -2299,6 +2685,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ieee80211_conf *conf = &hw->conf; struct ath_hw *ah = sc->sc_ah; bool all_wiphys_idle = false, disable_radio = false; @@ -2318,8 +2705,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) } else if (all_wiphys_idle) { ath_radio_enable(sc); - DPRINTF(sc, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); + ath_print(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); } } @@ -2337,7 +2724,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) sc->ps_enabled = true; } else { sc->ps_enabled = false; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + ath9k_setpower(sc, ATH9K_PM_AWAKE); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { ath9k_hw_setrxabort(sc->sc_ah, 0); @@ -2372,8 +2759,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) goto skip_chan_change; } - DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); + ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); /* XXX: remove me eventualy */ ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); @@ -2381,7 +2768,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath_update_chainmask(sc, conf_is_ht(conf)); if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { - DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); + ath_print(common, ATH_DBG_FATAL, + "Unable to set channel\n"); mutex_unlock(&sc->mutex); return -EINVAL; } @@ -2392,7 +2780,7 @@ skip_chan_change: sc->config.txpowlimit = 2 * conf->power_level; if (disable_radio) { - DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n"); + ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); ath_radio_disable(sc); } @@ -2429,7 +2817,8 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, ath9k_hw_setrxfilter(sc->sc_ah, rfilt); ath9k_ps_restore(sc); - DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", rfilt); + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, + "Set HW RX filter: 0x%x\n", rfilt); } static void ath9k_sta_notify(struct ieee80211_hw *hw, @@ -2457,6 +2846,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_tx_queue_info qi; int ret = 0, qnum; @@ -2473,15 +2863,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, qi.tqi_burstTime = params->txop; qnum = ath_get_hal_qnum(queue, sc); - DPRINTF(sc, ATH_DBG_CONFIG, - "Configure tx [queue/halq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); + ath_print(common, ATH_DBG_CONFIG, + "Configure tx [queue/halq] [%d/%d], " + "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); ret = ath_txq_update(sc, qnum, &qi); if (ret) - DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n"); + ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); mutex_unlock(&sc->mutex); @@ -2496,6 +2886,7 @@ static int ath9k_set_key(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); int ret = 0; if (modparam_nohwcrypt) @@ -2503,7 +2894,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); - DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); + ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); switch (cmd) { case SET_KEY: @@ -2540,6 +2931,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ath_vif *avp = (void *)vif->drv_priv; u32 rfilt = 0; int error, i; @@ -2555,9 +2947,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ah->opmode != NL80211_IFTYPE_AP) { ah->opmode = NL80211_IFTYPE_STATION; ath9k_hw_setopmode(ah); - memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); + memcpy(common->curbssid, common->macaddr, ETH_ALEN); + common->curaid = 0; + ath9k_hw_write_associd(ah); /* Request full reset to get hw opmode changed properly */ sc->sc_flags |= SC_OP_FULL_RESET; } @@ -2569,17 +2961,17 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: /* Set BSSID */ - memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN); + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); + common->curaid = 0; + ath9k_hw_write_associd(ah); /* Set aggregation protection mode parameters */ sc->config.ath_aggr_prot = 0; - DPRINTF(sc, ATH_DBG_CONFIG, - "RX filter 0x%x bssid %pM aid 0x%x\n", - rfilt, sc->curbssid, sc->curaid); + ath_print(common, ATH_DBG_CONFIG, + "RX filter 0x%x bssid %pM aid 0x%x\n", + rfilt, common->curbssid, common->curaid); /* need to reconfigure the beacon */ sc->sc_flags &= ~SC_OP_BEACONS ; @@ -2618,7 +3010,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) ath9k_hw_keysetmac(sc->sc_ah, (u16)i, - sc->curbssid); + common->curbssid); } /* Only legacy IBSS for now */ @@ -2626,8 +3018,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath_update_chainmask(sc, 0); if (changed & BSS_CHANGED_ERP_PREAMBLE) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); + ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) sc->sc_flags |= SC_OP_PREAMBLE_SHORT; else @@ -2635,8 +3027,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); + ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && hw->conf.channel->band != IEEE80211_BAND_5GHZ) sc->sc_flags |= SC_OP_PROTECT_ENABLE; @@ -2645,7 +3037,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ASSOC) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); ath9k_bss_assoc_info(sc, vif, bss_conf); } @@ -2694,7 +3086,11 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw) struct ath_softc *sc = aphy->sc; mutex_lock(&sc->mutex); + + ath9k_ps_wakeup(sc); ath9k_hw_reset_tsf(sc->sc_ah); + ath9k_ps_restore(sc); + mutex_unlock(&sc->mutex); } @@ -2726,7 +3122,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ath_tx_aggr_resume(sc, sta, tid); break; default: - DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, + "Unknown AMPDU action\n"); } return ret; @@ -2794,64 +3191,6 @@ struct ieee80211_ops ath9k_ops = { .rfkill_poll = ath9k_rfkill_poll_state, }; -static struct { - u32 version; - const char * name; -} ath_mac_bb_names[] = { - { AR_SREV_VERSION_5416_PCI, "5416" }, - { AR_SREV_VERSION_5416_PCIE, "5418" }, - { AR_SREV_VERSION_9100, "9100" }, - { AR_SREV_VERSION_9160, "9160" }, - { AR_SREV_VERSION_9280, "9280" }, - { AR_SREV_VERSION_9285, "9285" }, - { AR_SREV_VERSION_9287, "9287" } -}; - -static struct { - u16 version; - const char * name; -} ath_rf_names[] = { - { 0, "5133" }, - { AR_RAD5133_SREV_MAJOR, "5133" }, - { AR_RAD5122_SREV_MAJOR, "5122" }, - { AR_RAD2133_SREV_MAJOR, "2133" }, - { AR_RAD2122_SREV_MAJOR, "2122" } -}; - -/* - * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. - */ -const char * -ath_mac_bb_name(u32 mac_bb_version) -{ - int i; - - for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) { - if (ath_mac_bb_names[i].version == mac_bb_version) { - return ath_mac_bb_names[i].name; - } - } - - return "????"; -} - -/* - * Return the RF name. "????" is returned if the RF is unknown. - */ -const char * -ath_rf_name(u16 rf_version) -{ - int i; - - for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) { - if (ath_rf_names[i].version == rf_version) { - return ath_rf_names[i].name; - } - } - - return "????"; -} - static int __init ath9k_init(void) { int error; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 903dd8a..5321f73 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -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) @@ -92,6 +114,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) u32 val; int ret = 0; struct ath_hw *ah; + char hw_name[64]; if (pci_enable_device(pdev)) return -EIO; @@ -177,10 +200,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; @@ -197,14 +219,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->irq = pdev->irq; ah = sc->sc_ah; + ath9k_hw_name(ah, hw_name, sizeof(hw_name)); printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x " - "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", + "%s: %s mem=0x%lx, irq=%d\n", wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev, + hw_name, (unsigned long)mem, pdev->irq); return 0; diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index 63bf9a3..13ab4d7 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c @@ -14,90 +14,70 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "ath9k.h" +/** + * DOC: Programming Atheros 802.11n analog front end radios + * + * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express + * devices have either an external AR2133 analog front end radio for single + * band 2.4 GHz communication or an AR5133 analog front end radio for dual + * band 2.4 GHz / 5 GHz communication. + * + * All devices after the AR5416 and AR5418 family starting with the AR9280 + * have their analog front radios, MAC/BB and host PCIe/USB interface embedded + * into a single-chip and require less programming. + * + * The following single-chips exist with a respective embedded radio: + * + * AR9280 - 11n dual-band 2x2 MIMO for PCIe + * AR9281 - 11n single-band 1x2 MIMO for PCIe + * AR9285 - 11n single-band 1x1 for PCIe + * AR9287 - 11n single-band 2x2 MIMO for PCIe + * + * AR9220 - 11n dual-band 2x2 MIMO for PCI + * AR9223 - 11n single-band 2x2 MIMO for PCI + * + * AR9287 - 11n single-band 1x1 MIMO for USB + */ -void -ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, - int regWrites) -{ - REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); -} +#include "hw.h" -bool -ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +/** + * ath9k_hw_write_regs - ?? + * + * @ah: atheros hardware structure + * @freqIndex: + * @regWrites: + * + * Used for both the chipsets with an external AR2133/AR5133 radios and + * single-chip devices. + */ +void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites) { - u32 channelSel = 0; - u32 bModeSynth = 0; - u32 aModeRefSel = 0; - u32 reg32 = 0; - u16 freq; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - if (freq < 4800) { - u32 txctl; - - if (((freq - 2192) % 5) == 0) { - channelSel = ((freq - 672) * 2 - 3040) / 10; - bModeSynth = 0; - } else if (((freq - 2224) % 5) == 0) { - channelSel = ((freq - 704) * 2 - 3040) / 10; - bModeSynth = 1; - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return false; - } - - channelSel = (channelSel << 2) & 0xff; - channelSel = ath9k_hw_reverse_bits(channelSel, 8); - - 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); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - - } else if ((freq % 20) == 0 && freq >= 5120) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 10) == 0) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) - aModeRefSel = ath9k_hw_reverse_bits(2, 2); - else - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 5) == 0) { - 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); - return false; - } - - reg32 = - (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | - (1 << 5) | 0x1; - - REG_WRITE(ah, AR_PHY(0x37), reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return true; + REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); } -void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan) +/** + * ath9k_hw_ar9280_set_channel - set channel on single-chip device + * @ah: atheros hardware structure + * @chan: + * + * This is the function to change channel on single-chip devices, that is + * all devices after ar9280. + * + * This function takes the channel value in MHz and sets + * hardware channel value. Assumes writes have been enabled to analog bus. + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + */ +int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) { u16 bMode, fracMode, aModeRefSel = 0; u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; @@ -110,22 +90,34 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); reg32 &= 0xc0000000; - if (freq < 4800) { + if (freq < 4800) { /* 2 GHz, fractional mode */ 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) { + /* Enable channel spreading for channel 14 */ + 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; @@ -143,10 +135,15 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, case 1: default: aModeRefSel = 0; + /* + * Enable 2G (fractional) mode for channels + * which are 5MHz spaced. + */ fracMode = 1; refDivA = 1; channelSel = (freq * 0x8000) / 15; + /* RefDivA setting */ REG_RMW_FIELD(ah, AR_AN_SYNTH9, AR_AN_SYNTH9_REFDIVA, refDivA); @@ -168,12 +165,284 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, ah->curchan = chan; ah->curchan_rad_index = -1; + + return 0; } -static void -ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, - u32 numBits, u32 firstBit, - u32 column) +/** + * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency + * @ah: atheros hardware structure + * @chan: + * + * For single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + */ +void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int freq; + int bin, cur_bin; + int bb_spur_off, spur_subchannel_sd; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, newVal; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + struct chan_centers centers; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + ah->config.spurmode = SPUR_ENABLE_EEPROM; + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + + if (is2GHz) + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; + else + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - freq; + + if (IS_CHAN_HT40(chan)) { + if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { + bb_spur = cur_bb_spur; + break; + } + } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + return; + } else { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + } + + bin = bb_spur * 320; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); + + newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + + if (IS_CHAN_HT40(chan)) { + if (bb_spur < 0) { + spur_subchannel_sd = 1; + bb_spur_off = bb_spur + 10; + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur - 10; + } + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur; + } + + if (IS_CHAN_HT40(chan)) + spur_delta_phase = + ((bb_spur * 262144) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + else + spur_delta_phase = + ((bb_spur * 524288) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; + spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + + newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, newVal); + + newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; + REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +/* All code below is for non single-chip solutions */ + +/** + * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters + * @rfbuf: + * @reg32: + * @numBits: + * @firstBit: + * @column: + * + * Performs analog "swizzling" of parameters into their location. + * Used on external AR2133/AR5133 radios. + */ +static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, + u32 numBits, u32 firstBit, + u32 column) { u32 tmp32, mask, arrayEntry, lastBit; int32_t bitPosition, bitsLeft; @@ -197,26 +466,556 @@ ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, } } -bool -ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, - u16 modesIndex) +/* + * Fix on 2.4 GHz band for orientation sensitivity issue by increasing + * rf_pwd_icsyndiv. + * + * Theoretical Rules: + * if 2 GHz band + * if forceBiasAuto + * if synth_freq < 2412 + * bias = 0 + * else if 2412 <= synth_freq <= 2422 + * bias = 1 + * else // synth_freq > 2422 + * bias = 2 + * else if forceBias > 0 + * bias = forceBias & 7 + * else + * no change, use value from ini file + * else + * no change, invalid band + * + * 1st Mod: + * 2422 also uses value of 2 + * <approved> + * + * 2nd Mod: + * Less than 2412 uses value of 0, 2412 and above uses value of 2 + */ +static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 tmp_reg; + int reg_writes = 0; + u32 new_bias = 0; + + if (!AR_SREV_5416(ah) || synth_freq >= 3000) { + return; + } + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + if (synth_freq < 2412) + new_bias = 0; + else if (synth_freq < 2422) + new_bias = 1; + else + new_bias = 2; + + /* pre-reverse this field */ + tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); + + ath_print(common, ATH_DBG_CONFIG, + "Force rf_pwd_icsyndiv to %1d on %4d\n", + new_bias, synth_freq); + + /* swizzle rf_pwd_icsyndiv */ + ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); + + /* write Bank 6 with new params */ + REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); +} + +/** + * ath9k_hw_decrease_chain_power() + * + * @ah: atheros hardware structure + * @chan: + * + * Only used on the AR5416 and AR5418 with the external AR2133/AR5133 radios. + * + * Sets a chain internal RF path to the lowest output power. Any + * further writes to bank6 after this setting will override these + * changes. Thus this function must be the last function in the + * sequence to modify bank 6. + * + * This function must be called after ar5416SetRfRegs() which is + * called from ath9k_hw_process_ini() due to swizzling of bank 6. + * Depends on ah->analogBank6Data being initialized by + * ath9k_hw_set_rf_regs() + * + * Additional additive reduction in power - + * change chain's switch table so chain's tx state is actually the rx + * state value. May produce different results in 2GHz/5GHz as well as + * board to board but in general should be a reduction. + * + * Activated by #ifdef ALTER_SWITCH. Not tried yet. If so, must be + * called after ah->eep_ops->set_board_values() due to RMW of + * PHY_SWITCH_CHAIN_0. + */ +void ath9k_hw_decrease_chain_power(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + int i, regWrites = 0; + u32 bank6SelMask; + u32 *bank6Temp = ah->bank6Temp; + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + switch (ah->config.diversity_control) { + case ATH9K_ANT_FIXED_A: + bank6SelMask = + (ah->config.antenna_switch_swap & ANTSWAP_AB) ? + REDUCE_CHAIN_0 : /* swapped, reduce chain 0 */ + REDUCE_CHAIN_1; /* normal, select chain 1/2 to reduce */ + break; + case ATH9K_ANT_FIXED_B: + bank6SelMask = + (ah->config.antenna_switch_swap & ANTSWAP_AB) ? + REDUCE_CHAIN_1 : /* swapped, reduce chain 1/2 */ + REDUCE_CHAIN_0; /* normal, select chain 0 to reduce */ + break; + case ATH9K_ANT_VARIABLE: + return; /* do not change anything */ + break; + default: + return; /* do not change anything */ + break; + } + + for (i = 0; i < ah->iniBank6.ia_rows; i++) + bank6Temp[i] = ah->analogBank6Data[i]; + + /* Write Bank 5 to switch Bank 6 write to selected chain only */ + REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); + + /* + * Modify Bank6 selected chain to use lowest amplification. + * Modifies the parameters to a value of 1. + * Depends on existing bank 6 values to be cached in + * ah->analogBank6Data + */ + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); + + REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); + + REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); +#ifdef ALTER_SWITCH + REG_WRITE(ah, PHY_SWITCH_CHAIN_0, + (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) + | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); +#endif +} + +/** + * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios + * @ah: atheros hardware stucture + * @chan: + * + * For the external AR2133/AR5133 radios, takes the MHz channel value and set + * the channel value. Assumes writes enabled to analog bus and bank6 register + * cache in ah->analogBank6Data. + */ +int 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; + u32 reg32 = 0; + u16 freq; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { + u32 txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040) / 10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + ath_print(common, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return -EINVAL; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath9k_hw_reverse_bits(channelSel, 8); + + 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); + } else { + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); + } + + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); + if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) + aModeRefSel = ath9k_hw_reverse_bits(2, 2); + else + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else { + ath_print(common, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return -EINVAL; + } + + ath9k_hw_force_bias(ah, freq); + ath9k_hw_decrease_chain_power(ah, chan); + + reg32 = + (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 5) | 0x1; + + REG_WRITE(ah, AR_PHY(0x37), reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + + return 0; +} + +/** + * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios + * @ah: atheros hardware structure + * @chan: + * + * For non single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + */ +void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int bin, cur_bin; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, new; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - (chan->channel * 10); + if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) + return; + + bin = bb_spur * 32; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); + + new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, new); + + spur_delta_phase = ((bb_spur * 524288) / 100) & + AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; + spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + + new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, new); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +/** + * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming + * @ah: atheros hardware structure + * + * Only required for older devices with external AR2133/AR5133 radios. + */ +int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) +{ +#define ATH_ALLOC_BANK(bank, size) do { \ + bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ + if (!bank) { \ + ath_print(common, ATH_DBG_FATAL, \ + "Cannot allocate RF banks\n"); \ + return -ENOMEM; \ + } \ + } while (0); + + struct ath_common *common = ath9k_hw_common(ah); + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); + ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); + ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); + ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); + ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); + ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); + ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); + ATH_ALLOC_BANK(ah->addac5416_21, + ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); + ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); + + return 0; +#undef ATH_ALLOC_BANK +} + + +/** + * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers + * @ah: atheros hardware struture + * For the external AR2133/AR5133 radios banks. + */ +void +ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) +{ +#define ATH_FREE_BANK(bank) do { \ + kfree(bank); \ + bank = NULL; \ + } while (0); + + BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + + ATH_FREE_BANK(ah->analogBank0Data); + ATH_FREE_BANK(ah->analogBank1Data); + ATH_FREE_BANK(ah->analogBank2Data); + ATH_FREE_BANK(ah->analogBank3Data); + ATH_FREE_BANK(ah->analogBank6Data); + ATH_FREE_BANK(ah->analogBank6TPCData); + ATH_FREE_BANK(ah->analogBank7Data); + ATH_FREE_BANK(ah->addac5416_21); + ATH_FREE_BANK(ah->bank6Temp); + +#undef ATH_FREE_BANK +} + +/* * + * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM + * @ah: atheros hardware structure + * @chan: + * @modesIndex: + * + * Used for the external AR2133/AR5133 radios. + * + * Reads the EEPROM header info from the device structure and programs + * all rf registers. This routine requires access to the analog + * rf device. This is not required for single-chip devices. + */ +bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, + u16 modesIndex) { u32 eepMinorRev; u32 ob5GHz = 0, db5GHz = 0; u32 ob2GHz = 0, db2GHz = 0; int regWrites = 0; + /* + * Software does not need to program bank data + * for single chip devices, that is AR9280 or anything + * after that. + */ if (AR_SREV_9280_10_OR_LATER(ah)) return true; + /* Setup rf parameters */ eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); + /* Setup Bank 0 Write */ RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); + /* Setup Bank 1 Write */ RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); + /* Setup Bank 2 Write */ RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); + /* Setup Bank 6 Write */ RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, modesIndex); { @@ -227,6 +1026,7 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, } } + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ if (eepMinorRev >= 2) { if (IS_CHAN_2GHZ(chan)) { ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); @@ -245,8 +1045,10 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, } } + /* Setup Bank 7 Setup */ RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); + /* Write Analog registers */ REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, regWrites); REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, @@ -262,137 +1064,3 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, return true; } - -void -ath9k_hw_rf_free(struct ath_hw *ah) -{ -#define ATH_FREE_BANK(bank) do { \ - kfree(bank); \ - bank = NULL; \ - } while (0); - - ATH_FREE_BANK(ah->analogBank0Data); - ATH_FREE_BANK(ah->analogBank1Data); - ATH_FREE_BANK(ah->analogBank2Data); - ATH_FREE_BANK(ah->analogBank3Data); - ATH_FREE_BANK(ah->analogBank6Data); - ATH_FREE_BANK(ah->analogBank6TPCData); - ATH_FREE_BANK(ah->analogBank7Data); - ATH_FREE_BANK(ah->addac5416_21); - ATH_FREE_BANK(ah->bank6Temp); -#undef ATH_FREE_BANK -} - -bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) -{ - if (!AR_SREV_9280_10_OR_LATER(ah)) { - ah->analogBank0Data = - kzalloc((sizeof(u32) * - ah->iniBank0.ia_rows), GFP_KERNEL); - ah->analogBank1Data = - kzalloc((sizeof(u32) * - ah->iniBank1.ia_rows), GFP_KERNEL); - ah->analogBank2Data = - kzalloc((sizeof(u32) * - ah->iniBank2.ia_rows), GFP_KERNEL); - ah->analogBank3Data = - kzalloc((sizeof(u32) * - ah->iniBank3.ia_rows), GFP_KERNEL); - ah->analogBank6Data = - kzalloc((sizeof(u32) * - ah->iniBank6.ia_rows), GFP_KERNEL); - ah->analogBank6TPCData = - kzalloc((sizeof(u32) * - ah->iniBank6TPC.ia_rows), GFP_KERNEL); - ah->analogBank7Data = - kzalloc((sizeof(u32) * - ah->iniBank7.ia_rows), GFP_KERNEL); - - if (ah->analogBank0Data == NULL - || ah->analogBank1Data == NULL - || ah->analogBank2Data == NULL - || ah->analogBank3Data == NULL - || ah->analogBank6Data == NULL - || ah->analogBank6TPCData == NULL - || ah->analogBank7Data == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate RF banks\n"); - *status = -ENOMEM; - return false; - } - - ah->addac5416_21 = - kzalloc((sizeof(u32) * - 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"); - *status = -ENOMEM; - return false; - } - - ah->bank6Temp = - kzalloc((sizeof(u32) * - ah->iniBank6.ia_rows), GFP_KERNEL); - if (ah->bank6Temp == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate bank6Temp\n"); - *status = -ENOMEM; - return false; - } - } - - return true; -} - -void -ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int i, regWrites = 0; - u32 bank6SelMask; - u32 *bank6Temp = ah->bank6Temp; - - switch (ah->config.diversity_control) { - case ATH9K_ANT_FIXED_A: - bank6SelMask = - (ah->config.antenna_switch_swap & ANTSWAP_AB) ? - REDUCE_CHAIN_0 : REDUCE_CHAIN_1; - break; - case ATH9K_ANT_FIXED_B: - bank6SelMask = - (ah->config.antenna_switch_swap & ANTSWAP_AB) ? - REDUCE_CHAIN_1 : REDUCE_CHAIN_0; - break; - case ATH9K_ANT_VARIABLE: - return; - break; - default: - return; - break; - } - - for (i = 0; i < ah->iniBank6.ia_rows; i++) - bank6Temp[i] = ah->analogBank6Data[i]; - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); - - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); - - REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); -#ifdef ALTER_SWITCH - REG_WRITE(ah, PHY_SWITCH_CHAIN_0, - (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) - | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); -#endif -} diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index dfda6f4..dc145a1 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -17,20 +17,26 @@ #ifndef PHY_H #define PHY_H -void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel - *chan); -bool ath9k_hw_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan); -void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, - u32 freqIndex, int regWrites); +/* Common between single chip and non single-chip solutions */ +void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites); + +/* Single chip radio settings */ +int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); +void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); + +/* Routines below are for non single-chip solutions */ +int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); +void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); + +int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah); +void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah); + bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, u16 modesIndex); + void ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan); -bool ath9k_hw_init_rf(struct ath_hw *ah, - int *status); #define AR_PHY_BASE 0x9800 #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) @@ -45,6 +51,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 @@ -185,8 +192,20 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, #define AR_PHY_PLL_CTL_44_2133 0xeb #define AR_PHY_PLL_CTL_40_2133 0xea -#define AR_PHY_SPECTRAL_SCAN 0x9912 -#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 +#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */ +#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 +#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */ +#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */ +#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/ +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/ +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/ +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/ +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 +#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/ +#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/ +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/ #define AR_PHY_RX_DELAY 0x9914 #define AR_PHY_SEARCH_START_DELAY 0x9918 diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 1895d63..bb72b46 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -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; } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ec0abf8..355dd18 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -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 @@ -202,7 +202,8 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, } rcu_read_lock(); - sta = ieee80211_find_sta(sc->hw, hdr->addr2); + /* XXX: use ieee80211_find_sta! */ + sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr2); if (sta) { an = (struct ath_node *) sta->drv_priv; if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD && @@ -272,6 +273,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 +283,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 +298,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 +308,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 +338,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 +424,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 +534,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 +561,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 +574,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 +600,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 +663,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 +762,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 +824,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; } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d83b77f8..061e12c 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -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 @@ -1705,4 +1704,7 @@ enum { #define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) #define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) +#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ +#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ + #endif diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 19b88f8..bc7d173 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -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]; - - ath9k_hw_setbssidmask(sc); + 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]; + + 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 diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 42551a4..8e052f4 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -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) & @@ -282,7 +282,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, rcu_read_lock(); - sta = ieee80211_find_sta(sc->hw, hdr->addr1); + /* XXX: use ieee80211_find_sta! */ + sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr1); if (!sta) { rcu_read_unlock(); return; @@ -358,7 +359,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 +816,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 +856,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 +886,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 +916,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 +947,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 +957,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 +1057,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 +1079,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 +1151,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 +1176,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 +1193,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 +1457,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 +1513,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 +1593,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 +1676,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 +1690,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 +1720,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 +1745,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 +1756,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 +1779,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 +1817,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 +1949,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,8 +2078,11 @@ 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"); + ath9k_ps_wakeup(sc); ath_reset(sc, false); + ath9k_ps_restore(sc); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, @@ -2093,6 +2110,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 +2118,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; } diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c new file mode 100644 index 0000000..53e77bd --- /dev/null +++ b/drivers/net/wireless/ath/debug.c @@ -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); diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h new file mode 100644 index 0000000..d6b685a --- /dev/null +++ b/drivers/net/wireless/ath/debug.h @@ -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 */ diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c new file mode 100644 index 0000000..ecc9eb0 --- /dev/null +++ b/drivers/net/wireless/ath/hw.c @@ -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); diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h new file mode 100644 index 0000000..dfe1fbe --- /dev/null +++ b/drivers/net/wireless/ath/reg.h @@ -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 */ diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index c1dd857..a1c3952 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -65,10 +65,13 @@ enum CountryCode { CTRY_ALGERIA = 12, CTRY_ARGENTINA = 32, CTRY_ARMENIA = 51, + CTRY_ARUBA = 533, CTRY_AUSTRALIA = 36, CTRY_AUSTRIA = 40, CTRY_AZERBAIJAN = 31, CTRY_BAHRAIN = 48, + CTRY_BANGLADESH = 50, + CTRY_BARBADOS = 52, CTRY_BELARUS = 112, CTRY_BELGIUM = 56, CTRY_BELIZE = 84, @@ -77,6 +80,7 @@ enum CountryCode { CTRY_BRAZIL = 76, CTRY_BRUNEI_DARUSSALAM = 96, CTRY_BULGARIA = 100, + CTRY_CAMBODIA = 116, CTRY_CANADA = 124, CTRY_CHILE = 152, CTRY_CHINA = 156, @@ -97,7 +101,11 @@ enum CountryCode { CTRY_GEORGIA = 268, CTRY_GERMANY = 276, CTRY_GREECE = 300, + CTRY_GREENLAND = 304, + CTRY_GRENEDA = 308, + CTRY_GUAM = 316, CTRY_GUATEMALA = 320, + CTRY_HAITI = 332, CTRY_HONDURAS = 340, CTRY_HONG_KONG = 344, CTRY_HUNGARY = 348, diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 9847af7..248c670 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -288,13 +288,16 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_DEFAULT, FCC1_FCCA, "CO"}, {CTRY_ALBANIA, NULL1_WORLD, "AL"}, {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, - {CTRY_ARGENTINA, APL3_WORLD, "AR"}, + {CTRY_ARGENTINA, FCC3_WORLD, "AR"}, {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, + {CTRY_ARUBA, ETSI1_WORLD, "AW"}, {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, {CTRY_BAHRAIN, APL6_WORLD, "BH"}, + {CTRY_BANGLADESH, NULL1_WORLD, "BD"}, + {CTRY_BARBADOS, FCC2_WORLD, "BB"}, {CTRY_BELARUS, ETSI1_WORLD, "BY"}, {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, @@ -304,13 +307,14 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_BRAZIL, FCC3_WORLD, "BR"}, {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, - {CTRY_CANADA, FCC2_FCCA, "CA"}, + {CTRY_CAMBODIA, ETSI1_WORLD, "KH"}, + {CTRY_CANADA, FCC3_FCCA, "CA"}, {CTRY_CANADA2, FCC6_FCCA, "CA"}, {CTRY_CHILE, APL6_WORLD, "CL"}, {CTRY_CHINA, APL1_WORLD, "CN"}, {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, - {CTRY_CROATIA, ETSI3_WORLD, "HR"}, + {CTRY_CROATIA, ETSI1_WORLD, "HR"}, {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, {CTRY_CZECH, ETSI3_WORLD, "CZ"}, {CTRY_DENMARK, ETSI1_WORLD, "DK"}, @@ -324,18 +328,22 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, {CTRY_GERMANY, ETSI1_WORLD, "DE"}, {CTRY_GREECE, ETSI1_WORLD, "GR"}, + {CTRY_GREENLAND, ETSI1_WORLD, "GL"}, + {CTRY_GRENEDA, FCC3_FCCA, "GD"}, + {CTRY_GUAM, FCC1_FCCA, "GU"}, {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, + {CTRY_HAITI, ETSI1_WORLD, "HT"}, {CTRY_HONDURAS, NULL1_WORLD, "HN"}, - {CTRY_HONG_KONG, FCC2_WORLD, "HK"}, + {CTRY_HONG_KONG, FCC3_WORLD, "HK"}, {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, {CTRY_ICELAND, ETSI1_WORLD, "IS"}, {CTRY_INDIA, APL6_WORLD, "IN"}, - {CTRY_INDONESIA, APL1_WORLD, "ID"}, + {CTRY_INDONESIA, NULL1_WORLD, "ID"}, {CTRY_IRAN, APL1_WORLD, "IR"}, {CTRY_IRELAND, ETSI1_WORLD, "IE"}, {CTRY_ISRAEL, NULL1_WORLD, "IL"}, {CTRY_ITALY, ETSI1_WORLD, "IT"}, - {CTRY_JAMAICA, ETSI1_WORLD, "JM"}, + {CTRY_JAMAICA, FCC3_WORLD, "JM"}, {CTRY_JAPAN, MKK1_MKKA, "JP"}, {CTRY_JAPAN1, MKK1_MKKB, "JP"}, @@ -402,7 +410,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, - {CTRY_KUWAIT, NULL1_WORLD, "KW"}, + {CTRY_KUWAIT, ETSI3_WORLD, "KW"}, {CTRY_LATVIA, ETSI1_WORLD, "LV"}, {CTRY_LEBANON, NULL1_WORLD, "LB"}, {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, @@ -414,13 +422,13 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_MALTA, ETSI1_WORLD, "MT"}, {CTRY_MEXICO, FCC1_FCCA, "MX"}, {CTRY_MONACO, ETSI4_WORLD, "MC"}, - {CTRY_MOROCCO, NULL1_WORLD, "MA"}, + {CTRY_MOROCCO, APL4_WORLD, "MA"}, {CTRY_NEPAL, APL1_WORLD, "NP"}, {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, {CTRY_NORWAY, ETSI1_WORLD, "NO"}, - {CTRY_OMAN, APL6_WORLD, "OM"}, + {CTRY_OMAN, FCC3_WORLD, "OM"}, {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, {CTRY_PANAMA, FCC1_FCCA, "PA"}, {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, @@ -429,7 +437,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_POLAND, ETSI1_WORLD, "PL"}, {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, - {CTRY_QATAR, NULL1_WORLD, "QA"}, + {CTRY_QATAR, APL1_WORLD, "QA"}, {CTRY_ROMANIA, NULL1_WORLD, "RO"}, {CTRY_RUSSIA, NULL1_WORLD, "RU"}, {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, @@ -445,7 +453,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_SYRIA, NULL1_WORLD, "SY"}, {CTRY_TAIWAN, APL3_FCCA, "TW"}, {CTRY_THAILAND, FCC3_WORLD, "TH"}, - {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, + {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"}, {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, {CTRY_TURKEY, ETSI3_WORLD, "TR"}, {CTRY_UKRAINE, NULL1_WORLD, "UA"}, @@ -456,7 +464,7 @@ static struct country_code_to_enum_rd allCountries[] = { * would need to assign new special alpha2 to CRDA db as with the world * regdomain and use another alpha2 */ {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, - {CTRY_URUGUAY, APL2_WORLD, "UY"}, + {CTRY_URUGUAY, FCC3_WORLD, "UY"}, {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, |