- #endif
---- a/drivers/net/wireless/rtlwifi/base.c
-+++ b/drivers/net/wireless/rtlwifi/base.c
-@@ -173,6 +173,7 @@ u8 rtl_tid_to_ac(u8 tid)
- {
- return tid_to_ac[tid];
- }
-+EXPORT_SYMBOL_GPL(rtl_tid_to_ac);
-
- static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
- struct ieee80211_sta_ht_cap *ht_cap)
-@@ -407,6 +408,7 @@ void rtl_deinit_deferred_work(struct iee
- cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
- cancel_delayed_work(&rtlpriv->works.fwevt_wq);
- }
-+EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work);
-
- void rtl_init_rfkill(struct ieee80211_hw *hw)
- {
-@@ -440,6 +442,7 @@ void rtl_deinit_rfkill(struct ieee80211_
- {
- wiphy_rfkill_stop_polling(hw->wiphy);
- }
-+EXPORT_SYMBOL_GPL(rtl_deinit_rfkill);
-
- int rtl_init_core(struct ieee80211_hw *hw)
- {
-@@ -490,10 +493,12 @@ int rtl_init_core(struct ieee80211_hw *h
-
- return 0;
- }
-+EXPORT_SYMBOL_GPL(rtl_init_core);
-
- void rtl_deinit_core(struct ieee80211_hw *hw)
- {
- }
-+EXPORT_SYMBOL_GPL(rtl_deinit_core);
-
- void rtl_init_rx_config(struct ieee80211_hw *hw)
- {
-@@ -502,6 +507,7 @@ void rtl_init_rx_config(struct ieee80211
-
- rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf));
- }
-+EXPORT_SYMBOL_GPL(rtl_init_rx_config);
-
- /*********************************************************
- *
-@@ -880,6 +886,7 @@ bool rtl_tx_mgmt_proc(struct ieee80211_h
-
- return true;
- }
-+EXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc);
-
- void rtl_get_tcb_desc(struct ieee80211_hw *hw,
- struct ieee80211_tx_info *info,
-@@ -1053,6 +1060,7 @@ bool rtl_action_proc(struct ieee80211_hw
-
- return true;
- }
-+EXPORT_SYMBOL_GPL(rtl_action_proc);
-
- /*should call before software enc*/
- u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
-@@ -1126,6 +1134,7 @@ u8 rtl_is_special_data(struct ieee80211_
-
- return false;
- }
-+EXPORT_SYMBOL_GPL(rtl_is_special_data);
-
- /*********************************************************
- *
-@@ -1301,6 +1310,7 @@ void rtl_beacon_statistic(struct ieee802
-
- rtlpriv->link_info.bcn_rx_inperiod++;
- }
-+EXPORT_SYMBOL_GPL(rtl_beacon_statistic);
-
- void rtl_watchdog_wq_callback(void *data)
- {
-@@ -1794,6 +1804,7 @@ void rtl_recognize_peer(struct ieee80211
-
- mac->vendor = vendor;
- }
-+EXPORT_SYMBOL_GPL(rtl_recognize_peer);
-
- /*********************************************************
- *
-@@ -1850,6 +1861,7 @@ struct attribute_group rtl_attribute_gro
- .name = "rtlsysfs",
- .attrs = rtl_sysfs_entries,
- };
-+EXPORT_SYMBOL_GPL(rtl_attribute_group);
-
- MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
- MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
-@@ -1857,7 +1869,8 @@ MODULE_AUTHOR("Larry Finger <Larry.FInge
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
-
--struct rtl_global_var global_var = {};
-+struct rtl_global_var rtl_global_var = {};
-+EXPORT_SYMBOL_GPL(rtl_global_var);
-
- static int __init rtl_core_module_init(void)
- {
-@@ -1865,8 +1878,8 @@ static int __init rtl_core_module_init(v
- pr_err("Unable to register rtl_rc, use default RC !!\n");
-
- /* init some global vars */
-- INIT_LIST_HEAD(&global_var.glb_priv_list);
-- spin_lock_init(&global_var.glb_list_lock);
-+ INIT_LIST_HEAD(&rtl_global_var.glb_priv_list);
-+ spin_lock_init(&rtl_global_var.glb_list_lock);
-
- return 0;
- }
---- a/drivers/net/wireless/rtlwifi/base.h
-+++ b/drivers/net/wireless/rtlwifi/base.h
-@@ -147,7 +147,7 @@ void rtl_recognize_peer(struct ieee80211
- u8 rtl_tid_to_ac(u8 tid);
- extern struct attribute_group rtl_attribute_group;
- void rtl_easy_concurrent_retrytimer_callback(unsigned long data);
--extern struct rtl_global_var global_var;
-+extern struct rtl_global_var rtl_global_var;
- int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
- bool isht, u8 desc_rate, bool first_ampdu);
- bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
---- a/drivers/net/wireless/rtlwifi/core.c
-+++ b/drivers/net/wireless/rtlwifi/core.c
-@@ -1330,3 +1330,4 @@ const struct ieee80211_ops rtl_ops = {
- .rfkill_poll = rtl_op_rfkill_poll,
- .flush = rtl_op_flush,
- };
-+EXPORT_SYMBOL_GPL(rtl_ops);
---- a/drivers/net/wireless/rtlwifi/debug.c
-+++ b/drivers/net/wireless/rtlwifi/debug.c
-@@ -51,3 +51,4 @@ void rtl_dbgp_flag_init(struct ieee80211
-
- /*Init Debug flag enable condition */
- }
-+EXPORT_SYMBOL_GPL(rtl_dbgp_flag_init);
---- a/drivers/net/wireless/rtlwifi/efuse.c
-+++ b/drivers/net/wireless/rtlwifi/efuse.c
-@@ -229,6 +229,7 @@ void read_efuse_byte(struct ieee80211_hw
-
- *pbuf = (u8) (value32 & 0xff);
- }
-+EXPORT_SYMBOL_GPL(read_efuse_byte);
-
- void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
- {
---- a/drivers/net/wireless/rtlwifi/pci.c
-+++ b/drivers/net/wireless/rtlwifi/pci.c
-@@ -35,6 +35,13 @@
- #include "efuse.h"
- #include <linux/export.h>
- #include <linux/kmemleak.h>
-+#include <linux/module.h>
-+
-+MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
-+MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
-+MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("PCI basic driver for rtlwifi");
-
- static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
- PCI_VENDOR_ID_INTEL,
-@@ -1008,19 +1015,6 @@ static void _rtl_pci_prepare_bcn_tasklet
- return;
- }
-
--static void rtl_lps_change_work_callback(struct work_struct *work)
--{
-- struct rtl_works *rtlworks =
-- container_of(work, struct rtl_works, lps_change_work);
-- struct ieee80211_hw *hw = rtlworks->hw;
-- struct rtl_priv *rtlpriv = rtl_priv(hw);
--
-- if (rtlpriv->enter_ps)
-- rtl_lps_enter(hw);
-- else
-- rtl_lps_leave(hw);
--}
--
- static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
- {
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-@@ -1899,7 +1893,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
- rtlpriv->rtlhal.interface = INTF_PCI;
- rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data);
- rtlpriv->intf_ops = &rtl_pci_ops;
-- rtlpriv->glb_var = &global_var;
-+ rtlpriv->glb_var = &rtl_global_var;
-
- /*
- *init dbgp flags before all
---- a/drivers/net/wireless/rtlwifi/ps.c
-+++ b/drivers/net/wireless/rtlwifi/ps.c
-@@ -269,6 +269,7 @@ void rtl_ips_nic_on(struct ieee80211_hw
-
- spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
- }
-+EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
-
- /*for FW LPS*/
-
-@@ -518,6 +519,7 @@ void rtl_swlps_beacon(struct ieee80211_h
- "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
- }
- }
-+EXPORT_SYMBOL_GPL(rtl_swlps_beacon);
-
- void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
- {
-@@ -611,6 +613,19 @@ void rtl_swlps_rf_sleep(struct ieee80211
- MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
- }
-
-+void rtl_lps_change_work_callback(struct work_struct *work)
-+{
-+ struct rtl_works *rtlworks =
-+ container_of(work, struct rtl_works, lps_change_work);
-+ struct ieee80211_hw *hw = rtlworks->hw;
-+ struct rtl_priv *rtlpriv = rtl_priv(hw);
-+
-+ if (rtlpriv->enter_ps)
-+ rtl_lps_enter(hw);
-+ else
-+ rtl_lps_leave(hw);
-+}
-+EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
-
- void rtl_swlps_wq_callback(void *data)
- {
-@@ -922,3 +937,4 @@ void rtl_p2p_info(struct ieee80211_hw *h
- else
- rtl_p2p_noa_ie(hw, data, len - FCS_LEN);
- }
-+EXPORT_SYMBOL_GPL(rtl_p2p_info);
---- a/drivers/net/wireless/rtlwifi/usb.c
-+++ b/drivers/net/wireless/rtlwifi/usb.c
-@@ -32,6 +32,13 @@
- #include "ps.h"
- #include "rtl8192c/fw_common.h"
- #include <linux/export.h>
-+#include <linux/module.h>
-+
-+MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
-+MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
-+MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("USB basic driver for rtlwifi");
-
- #define REALTEK_USB_VENQT_READ 0xC0
- #define REALTEK_USB_VENQT_WRITE 0x40
-@@ -1070,6 +1077,8 @@ int rtl_usb_probe(struct usb_interface *
- spin_lock_init(&rtlpriv->locks.usb_lock);
- INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
- rtl_fill_h2c_cmd_work_callback);
-+ INIT_WORK(&rtlpriv->works.lps_change_work,
-+ rtl_lps_change_work_callback);
-
- rtlpriv->usb_data_index = 0;
- init_completion(&rtlpriv->firmware_loading_complete);
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -72,17 +72,12 @@ struct ath_config {
- /*************************/
-
- #define ATH_TXBUF_RESET(_bf) do { \
-- (_bf)->bf_stale = false; \
- (_bf)->bf_lastbf = NULL; \
- (_bf)->bf_next = NULL; \
- memset(&((_bf)->bf_state), 0, \
- sizeof(struct ath_buf_state)); \
- } while (0)
-
--#define ATH_RXBUF_RESET(_bf) do { \
-- (_bf)->bf_stale = false; \
-- } while (0)
--
- /**
- * enum buffer_type - Buffer type flags
- *
-@@ -137,7 +132,8 @@ int ath_descdma_setup(struct ath_softc *
- #define ATH_AGGR_ENCRYPTDELIM 10
- /* minimum h/w qdepth to be sustained to maximize aggregation */
- #define ATH_AGGR_MIN_QDEPTH 2
--#define ATH_AMPDU_SUBFRAME_DEFAULT 32
-+/* minimum h/w qdepth for non-aggregated traffic */
-+#define ATH_NON_AGGR_MIN_QDEPTH 8
-
- #define IEEE80211_SEQ_SEQ_SHIFT 4
- #define IEEE80211_SEQ_MAX 4096
-@@ -174,12 +170,6 @@ int ath_descdma_setup(struct ath_softc *
-
- #define ATH_TX_COMPLETE_POLL_INT 1000
-
--enum ATH_AGGR_STATUS {
-- ATH_AGGR_DONE,
-- ATH_AGGR_BAW_CLOSED,
-- ATH_AGGR_LIMITED,
--};
--
- #define ATH_TXFIFO_DEPTH 8
- struct ath_txq {
- int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
-@@ -201,10 +191,10 @@ struct ath_txq {
-
- struct ath_atx_ac {
- struct ath_txq *txq;
-- int sched;
- struct list_head list;
- struct list_head tid_q;
- bool clear_ps_filter;
-+ bool sched;
- };
-
- struct ath_frame_info {
-@@ -212,14 +202,16 @@ struct ath_frame_info {
- int framelen;
- enum ath9k_key_type keytype;
- u8 keyix;
-- u8 retries;
- u8 rtscts_rate;
-+ u8 retries : 7;
-+ u8 baw_tracked : 1;
- };
-
- struct ath_buf_state {
- u8 bf_type;
- u8 bfs_paprd;
- u8 ndelim;
-+ bool stale;
- u16 seqno;
- unsigned long bfs_paprd_timestamp;
- };
-@@ -233,7 +225,6 @@ struct ath_buf {
- void *bf_desc; /* virtual addr of desc */
- dma_addr_t bf_daddr; /* physical addr of desc */
- dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
-- bool bf_stale;
- struct ieee80211_tx_rate rates[4];
- struct ath_buf_state bf_state;
- };
-@@ -241,16 +232,18 @@ struct ath_buf {
- struct ath_atx_tid {
- struct list_head list;
- struct sk_buff_head buf_q;
-+ struct sk_buff_head retry_q;
- struct ath_node *an;
- struct ath_atx_ac *ac;
- unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
-- int bar_index;
- u16 seq_start;
- u16 seq_next;
- u16 baw_size;
-- int tidno;
-+ u8 tidno;
- int baw_head; /* first un-acked tx buffer */
- int baw_tail; /* next unused tx buffer slot */
-+
-+ s8 bar_index;
- bool sched;
- bool paused;
- bool active;
-@@ -262,12 +255,13 @@ struct ath_node {
- struct ieee80211_vif *vif; /* interface with which we're associated */
- struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
- struct ath_atx_ac ac[IEEE80211_NUM_ACS];
-- int ps_key;
-
- u16 maxampdu;
- u8 mpdudensity;
-+ s8 ps_key;
-
- bool sleeping;
-+ bool no_ps_filter;
-
- #if defined(CPTCFG_MAC80211_DEBUGFS) && defined(CPTCFG_ATH9K_DEBUGFS)
- struct dentry *node_stat;
-@@ -317,6 +311,7 @@ struct ath_rx {
- struct ath_descdma rxdma;
- struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
-
-+ struct ath_buf *buf_hold;
- struct sk_buff *frag;
-
- u32 ampdu_ref;
-@@ -367,6 +362,7 @@ void ath9k_release_buffered_frames(struc
- /********/
-
- struct ath_vif {
-+ struct ath_node mcast_node;
- int av_bslot;
- bool primary_sta_vif;
- __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
-@@ -585,19 +581,14 @@ static inline void ath_fill_led_pin(stru
- #define ATH_ANT_DIV_COMB_MAX_COUNT 100
- #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
- #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
-+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50
-+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50
-
- #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
- #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
- #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2
- #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2
-
--enum ath9k_ant_div_comb_lna_conf {
-- ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
-- ATH_ANT_DIV_COMB_LNA2,
-- ATH_ANT_DIV_COMB_LNA1,
-- ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
--};
--
- struct ath_ant_comb {
- u16 count;
- u16 total_pkt_count;
-@@ -614,27 +605,36 @@ struct ath_ant_comb {
- int rssi_first;
- int rssi_second;
- int rssi_third;
-+ int ant_ratio;
-+ int ant_ratio2;
- bool alt_good;
- int quick_scan_cnt;
-- int main_conf;
-+ enum ath9k_ant_div_comb_lna_conf main_conf;
- enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf;
- enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf;
- bool first_ratio;
- bool second_ratio;
- unsigned long scan_start_time;
-+
-+ /*
-+ * Card-specific config values.
-+ */
-+ int low_rssi_thresh;
-+ int fast_div_bias;
- };
-
- void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
--void ath_ant_comb_update(struct ath_softc *sc);
-
- /********************/
- /* Main driver core */
- /********************/
-
--#define ATH9K_PCI_CUS198 0x0001
--#define ATH9K_PCI_CUS230 0x0002
--#define ATH9K_PCI_CUS217 0x0004
--#define ATH9K_PCI_WOW 0x0008
-+#define ATH9K_PCI_CUS198 0x0001
-+#define ATH9K_PCI_CUS230 0x0002
-+#define ATH9K_PCI_CUS217 0x0004
-+#define ATH9K_PCI_WOW 0x0008
-+#define ATH9K_PCI_BT_ANT_DIV 0x0010
-+#define ATH9K_PCI_D3_L1_WAR 0x0020
-
- /*
- * Default cache line size, in bytes.
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -270,25 +270,29 @@ static const struct file_operations fops
- .llseek = default_llseek,
- };
-
--static ssize_t read_file_ant_diversity(struct file *file, char __user *user_buf,
-- size_t count, loff_t *ppos)
-+#ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-+
-+static ssize_t read_file_bt_ant_diversity(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 = sprintf(buf, "%d\n", common->antenna_diversity);
-+ len = sprintf(buf, "%d\n", common->bt_ant_diversity);
- return simple_read_from_buffer(user_buf, count, ppos, buf, len);
- }
-
--static ssize_t write_file_ant_diversity(struct file *file,
-- const char __user *user_buf,
-- size_t count, loff_t *ppos)
-+static ssize_t write_file_bt_ant_diversity(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 antenna_diversity;
-+ struct ath9k_hw_capabilities *pCap = &sc->sc_ah->caps;
-+ unsigned long bt_ant_diversity;
- char buf[32];
- ssize_t len;
-
-@@ -296,26 +300,147 @@ static ssize_t write_file_ant_diversity(
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
-
-- if (!AR_SREV_9565(sc->sc_ah))
-+ if (!(pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV))
- goto exit;
-
- buf[len] = '\0';
-- if (strict_strtoul(buf, 0, &antenna_diversity))
-+ if (kstrtoul(buf, 0, &bt_ant_diversity))
- return -EINVAL;
-
-- common->antenna_diversity = !!antenna_diversity;
-+ common->bt_ant_diversity = !!bt_ant_diversity;
- ath9k_ps_wakeup(sc);
-- ath_ant_comb_update(sc);
-- ath_dbg(common, CONFIG, "Antenna diversity: %d\n",
-- common->antenna_diversity);
-+ ath9k_hw_set_bt_ant_diversity(sc->sc_ah, common->bt_ant_diversity);
-+ ath_dbg(common, CONFIG, "Enable WLAN/BT RX Antenna diversity: %d\n",
-+ common->bt_ant_diversity);
- ath9k_ps_restore(sc);
- exit:
- return count;
- }
-
--static const struct file_operations fops_ant_diversity = {
-- .read = read_file_ant_diversity,
-- .write = write_file_ant_diversity,
-+static const struct file_operations fops_bt_ant_diversity = {
-+ .read = read_file_bt_ant_diversity,
-+ .write = write_file_bt_ant_diversity,
-+ .open = simple_open,
-+ .owner = THIS_MODULE,
-+ .llseek = default_llseek,
-+};
-+
-+#endif
-+
-+void ath9k_debug_stat_ant(struct ath_softc *sc,
-+ struct ath_hw_antcomb_conf *div_ant_conf,
-+ int main_rssi_avg, int alt_rssi_avg)
-+{
-+ struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN];
-+ struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT];
-+
-+ as_main->lna_attempt_cnt[div_ant_conf->main_lna_conf]++;
-+ as_alt->lna_attempt_cnt[div_ant_conf->alt_lna_conf]++;
-+
-+ as_main->rssi_avg = main_rssi_avg;
-+ as_alt->rssi_avg = alt_rssi_avg;
-+}
-+
-+static ssize_t read_file_antenna_diversity(struct file *file,
-+ char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ath9k_hw_capabilities *pCap = &ah->caps;
-+ struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN];
-+ struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT];
-+ struct ath_hw_antcomb_conf div_ant_conf;
-+ unsigned int len = 0, size = 1024;
-+ ssize_t retval = 0;
-+ char *buf;
-+ char *lna_conf_str[4] = {"LNA1_MINUS_LNA2",
-+ "LNA2",
-+ "LNA1",
-+ "LNA1_PLUS_LNA2"};
-+
-+ buf = kzalloc(size, GFP_KERNEL);
-+ if (buf == NULL)
-+ return -ENOMEM;
-+
-+ if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) {
-+ len += snprintf(buf + len, size - len, "%s\n",
-+ "Antenna Diversity Combining is disabled");
-+ goto exit;
-+ }
-+
-+ ath9k_ps_wakeup(sc);
-+ ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
-+ len += snprintf(buf + len, size - len, "Current MAIN config : %s\n",
-+ lna_conf_str[div_ant_conf.main_lna_conf]);
-+ len += snprintf(buf + len, size - len, "Current ALT config : %s\n",
-+ lna_conf_str[div_ant_conf.alt_lna_conf]);
-+ len += snprintf(buf + len, size - len, "Average MAIN RSSI : %d\n",
-+ as_main->rssi_avg);
-+ len += snprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n",
-+ as_alt->rssi_avg);
-+ ath9k_ps_restore(sc);
-+
-+ len += snprintf(buf + len, size - len, "Packet Receive Cnt:\n");
-+ len += snprintf(buf + len, size - len, "-------------------\n");
-+
-+ len += snprintf(buf + len, size - len, "%30s%15s\n",
-+ "MAIN", "ALT");
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "TOTAL COUNT",
-+ as_main->recv_cnt,
-+ as_alt->recv_cnt);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA1",
-+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1],
-+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA2",
-+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2],
-+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA1 + LNA2",
-+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
-+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA1 - LNA2",
-+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
-+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
-+
-+ len += snprintf(buf + len, size - len, "\nLNA Config Attempts:\n");
-+ len += snprintf(buf + len, size - len, "--------------------\n");
-+
-+ len += snprintf(buf + len, size - len, "%30s%15s\n",
-+ "MAIN", "ALT");
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA1",
-+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1],
-+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA2",
-+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2],
-+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA1 + LNA2",
-+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
-+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
-+ len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
-+ "LNA1 - LNA2",
-+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
-+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
-+
-+exit:
-+ if (len > size)
-+ len = size;
-+
-+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+ kfree(buf);
-+
-+ return retval;
-+}
-+
-+static const struct file_operations fops_antenna_diversity = {
-+ .read = read_file_antenna_diversity,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-@@ -607,6 +732,28 @@ static ssize_t read_file_xmit(struct fil
- return retval;
- }
-
-+static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq,
-+ char *buf, ssize_t size)
-+{
-+ ssize_t len = 0;
-+
-+ ath_txq_lock(sc, txq);
-+
-+ len += snprintf(buf + len, size - len, "%s: %d ",
-+ "qnum", txq->axq_qnum);
-+ len += snprintf(buf + len, size - len, "%s: %2d ",
-+ "qdepth", txq->axq_depth);
-+ len += snprintf(buf + len, size - len, "%s: %2d ",
-+ "ampdu-depth", txq->axq_ampdu_depth);
-+ len += snprintf(buf + len, size - len, "%s: %3d ",
-+ "pending", txq->pending_frames);
-+ len += snprintf(buf + len, size - len, "%s: %d\n",
-+ "stopped", txq->stopped);
-+
-+ ath_txq_unlock(sc, txq);
-+ return len;
-+}
-+
- static ssize_t read_file_queues(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
- {
-@@ -624,24 +771,13 @@ static ssize_t read_file_queues(struct f
-
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- txq = sc->tx.txq_map[i];
-- len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
--
-- ath_txq_lock(sc, txq);
--
-- len += snprintf(buf + len, size - len, "%s: %d ",
-- "qnum", txq->axq_qnum);
-- len += snprintf(buf + len, size - len, "%s: %2d ",
-- "qdepth", txq->axq_depth);
-- len += snprintf(buf + len, size - len, "%s: %2d ",
-- "ampdu-depth", txq->axq_ampdu_depth);
-- len += snprintf(buf + len, size - len, "%s: %3d ",
-- "pending", txq->pending_frames);
-- len += snprintf(buf + len, size - len, "%s: %d\n",
-- "stopped", txq->stopped);
--
-- ath_txq_unlock(sc, txq);
-+ len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
-+ len += print_queue(sc, txq, buf + len, size - len);
- }
-
-+ len += snprintf(buf + len, size - len, "(CAB): ");
-+ len += print_queue(sc, sc->beacon.cabq, buf + len, size - len);
-+
- if (len > size)
- len = size;
-
-@@ -1818,9 +1954,11 @@ int ath9k_init_debug(struct ath_hw *ah)
- sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
- debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
- sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
-- debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
-- sc->debug.debugfs_phy, sc, &fops_ant_diversity);
-+ debugfs_create_file("antenna_diversity", S_IRUSR,
-+ sc->debug.debugfs_phy, sc, &fops_antenna_diversity);
- #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-+ debugfs_create_file("bt_ant_diversity", S_IRUSR | S_IWUSR,
-+ sc->debug.debugfs_phy, sc, &fops_bt_ant_diversity);
- debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_btcoex);
- #endif
---- a/net/mac80211/ibss.c
-+++ b/net/mac80211/ibss.c
-@@ -30,13 +30,14 @@
-
- #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
- #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
-+#define IEEE80211_IBSS_RSN_INACTIVITY_LIMIT (10 * HZ)
-
- #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
-
-
- static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
- const u8 *bssid, const int beacon_int,
-- struct ieee80211_channel *chan,
-+ struct cfg80211_chan_def *req_chandef,
- const u32 basic_rates,
- const u16 capability, u64 tsf,
- bool creator)
-@@ -51,6 +52,7 @@ static void __ieee80211_sta_join_ibss(st
- u32 bss_change;
- u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
- struct cfg80211_chan_def chandef;
-+ struct ieee80211_channel *chan;
- struct beacon_data *presp;
- int frame_len;
-
-@@ -81,7 +83,9 @@ static void __ieee80211_sta_join_ibss(st
-
- sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
-
-- chandef = ifibss->chandef;
-+ /* make a copy of the chandef, it could be modified below. */
-+ chandef = *req_chandef;
-+ chan = chandef.chan;
- if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
- chandef.width = NL80211_CHAN_WIDTH_20;
- chandef.center_freq1 = chan->center_freq;
-@@ -259,10 +263,12 @@ static void ieee80211_sta_join_ibss(stru
- struct cfg80211_bss *cbss =
- container_of((void *)bss, struct cfg80211_bss, priv);
- struct ieee80211_supported_band *sband;
-+ struct cfg80211_chan_def chandef;
- u32 basic_rates;
- int i, j;
- u16 beacon_int = cbss->beacon_interval;
- const struct cfg80211_bss_ies *ies;
-+ enum nl80211_channel_type chan_type;
- u64 tsf;
-
- sdata_assert_lock(sdata);
-@@ -270,6 +276,26 @@ static void ieee80211_sta_join_ibss(stru
- if (beacon_int < 10)
- beacon_int = 10;
-
-+ switch (sdata->u.ibss.chandef.width) {
-+ case NL80211_CHAN_WIDTH_20_NOHT:
-+ case NL80211_CHAN_WIDTH_20:
-+ case NL80211_CHAN_WIDTH_40:
-+ chan_type = cfg80211_get_chandef_type(&sdata->u.ibss.chandef);
-+ cfg80211_chandef_create(&chandef, cbss->channel, chan_type);
-+ break;
-+ case NL80211_CHAN_WIDTH_5:
-+ case NL80211_CHAN_WIDTH_10:
-+ cfg80211_chandef_create(&chandef, cbss->channel,
-+ NL80211_CHAN_WIDTH_20_NOHT);
-+ chandef.width = sdata->u.ibss.chandef.width;
-+ break;
-+ default:
-+ /* fall back to 20 MHz for unsupported modes */
-+ cfg80211_chandef_create(&chandef, cbss->channel,
-+ NL80211_CHAN_WIDTH_20_NOHT);
-+ break;
-+ }
-+
- sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
-
- basic_rates = 0;
-@@ -294,7 +320,7 @@ static void ieee80211_sta_join_ibss(stru
-
- __ieee80211_sta_join_ibss(sdata, cbss->bssid,
- beacon_int,
-- cbss->channel,
-+ &chandef,
- basic_rates,
- cbss->capability,
- tsf, false);
-@@ -672,6 +698,33 @@ static int ieee80211_sta_active_ibss(str
- return active;
- }
-
-+static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct sta_info *sta, *tmp;
-+ unsigned long exp_time = IEEE80211_IBSS_INACTIVITY_LIMIT;
-+ unsigned long exp_rsn_time = IEEE80211_IBSS_RSN_INACTIVITY_LIMIT;
-+
-+ mutex_lock(&local->sta_mtx);
-+
-+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
-+ if (sdata != sta->sdata)
-+ continue;
-+
-+ if (time_after(jiffies, sta->last_rx + exp_time) ||
-+ (time_after(jiffies, sta->last_rx + exp_rsn_time) &&
-+ sta->sta_state != IEEE80211_STA_AUTHORIZED)) {
-+ sta_dbg(sta->sdata, "expiring inactive %sSTA %pM\n",
-+ sta->sta_state != IEEE80211_STA_AUTHORIZED ?
-+ "not authorized " : "", sta->sta.addr);
-+
-+ WARN_ON(__sta_info_destroy(sta));
-+ }
-+ }
-+
-+ mutex_unlock(&local->sta_mtx);
-+}
-+
- /*
- * This function is called with state == IEEE80211_IBSS_MLME_JOINED
- */
-@@ -685,7 +738,7 @@ static void ieee80211_sta_merge_ibss(str
- mod_timer(&ifibss->timer,
- round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
-
-- ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
-+ ieee80211_ibss_sta_expire(sdata);
-
- if (time_before(jiffies, ifibss->last_scan_completed +
- IEEE80211_IBSS_MERGE_INTERVAL))
-@@ -736,7 +789,7 @@ static void ieee80211_sta_create_ibss(st
- sdata->drop_unencrypted = 0;
-
- __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
-- ifibss->chandef.chan, ifibss->basic_rates,
-+ &ifibss->chandef, ifibss->basic_rates,
- capability, 0, true);
- }
-
-@@ -792,6 +845,17 @@ static void ieee80211_sta_find_ibss(stru
- return;
- }
-
-+ /* if a fixed bssid and a fixed freq have been provided create the IBSS
-+ * directly and do not waste time scanning
-+ */
-+ if (ifibss->fixed_bssid && ifibss->fixed_channel) {
-+ sdata_info(sdata, "Created IBSS using preconfigured BSSID %pM\n",
-+ bssid);
-+ ieee80211_sta_create_ibss(sdata);
-+ return;
-+ }
-+
-+
- ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n");
-
- /* Selected IBSS not found in current scan results - try to scan */
-@@ -1138,6 +1202,7 @@ int ieee80211_ibss_leave(struct ieee8021
- clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
- BSS_CHANGED_IBSS);
-+ ieee80211_vif_release_channel(sdata);
- synchronize_rcu();
- kfree(presp);
-
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -632,6 +632,22 @@ static void ar9003_hw_override_ini(struc
-
- REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
- AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
-+
-+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
-+ REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
-+ AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
-+
-+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
-+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
-+ ah->enabled_cals |= TX_IQ_CAL;
-+ else
-+ ah->enabled_cals &= ~TX_IQ_CAL;
-+
-+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
-+ ah->enabled_cals |= TX_CL_CAL;
-+ else
-+ ah->enabled_cals &= ~TX_CL_CAL;
-+ }
- }
-
- static void ar9003_hw_prog_ini(struct ath_hw *ah,
-@@ -814,29 +830,12 @@ static int ar9003_hw_process_ini(struct
- if (chan->channel == 2484)
- ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
-
-- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
-- REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
-- AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
--
- ah->modes_index = modesIndex;
- ar9003_hw_override_ini(ah);
- ar9003_hw_set_channel_regs(ah, chan);
- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
- ath9k_hw_apply_txpower(ah, chan, false);
-
-- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
-- if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
-- AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
-- ah->enabled_cals |= TX_IQ_CAL;
-- else
-- ah->enabled_cals &= ~TX_IQ_CAL;
--
-- if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
-- ah->enabled_cals |= TX_CL_CAL;
-- else
-- ah->enabled_cals &= ~TX_CL_CAL;
-- }
--
- return 0;
- }
-
-@@ -1173,6 +1172,10 @@ skip_ws_det:
- * is_on == 0 means MRC CCK is OFF (more noise imm)
- */
- bool is_on = param ? 1 : 0;
-+
-+ if (ah->caps.rx_chainmask == 1)
-+ break;
-+
- REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
- AR_PHY_MRC_CCK_ENABLE, is_on);
- REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
-@@ -1413,65 +1416,111 @@ static void ar9003_hw_antdiv_comb_conf_s
- REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
- }
-
--static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah,
-- bool enable)
-+#ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-+
-+static void ar9003_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
- {
-+ struct ath9k_hw_capabilities *pCap = &ah->caps;
- u8 ant_div_ctl1;
- u32 regval;
-
-- if (!AR_SREV_9565(ah))
-+ if (!AR_SREV_9485(ah) && !AR_SREV_9565(ah))
- return;
-
-- ah->shared_chain_lnadiv = enable;
-+ if (AR_SREV_9485(ah)) {
-+ regval = ar9003_hw_ant_ctrl_common_2_get(ah,
-+ IS_CHAN_2GHZ(ah->curchan));
-+ if (enable) {
-+ regval &= ~AR_SWITCH_TABLE_COM2_ALL;
-+ regval |= ah->config.ant_ctrl_comm2g_switch_enable;
-+ }
-+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2,
-+ AR_SWITCH_TABLE_COM2_ALL, regval);
-+ }
-+
- ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
-
-+ /*
-+ * Set MAIN/ALT LNA conf.
-+ * Set MAIN/ALT gain_tb.
-+ */
- regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
- regval &= (~AR_ANT_DIV_CTRL_ALL);
- regval |= (ant_div_ctl1 & 0x3f) << AR_ANT_DIV_CTRL_ALL_S;
-- regval &= ~AR_PHY_ANT_DIV_LNADIV;
-- regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
--
-- if (enable)
-- regval |= AR_ANT_DIV_ENABLE;
--
- REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
-
-- regval = REG_READ(ah, AR_PHY_CCK_DETECT);
-- regval &= ~AR_FAST_DIV_ENABLE;
-- regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
--
-- if (enable)
-- regval |= AR_FAST_DIV_ENABLE;
--
-- REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
--
-- if (enable) {
-- REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL,
-- (1 << AR_PHY_ANT_SW_RX_PROT_S));
-- if (ah->curchan && IS_CHAN_2GHZ(ah->curchan))
-- REG_SET_BIT(ah, AR_PHY_RESTART,
-- AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
-- REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
-- AR_BTCOEX_WL_LNADIV_FORCE_ON);
-- } else {
-- REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE);
-- REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
-- (1 << AR_PHY_ANT_SW_RX_PROT_S));
-- REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE);
-- REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
-- AR_BTCOEX_WL_LNADIV_FORCE_ON);
--
-+ if (AR_SREV_9485_11_OR_LATER(ah)) {
-+ /*
-+ * Enable LNA diversity.
-+ */
- regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
-- regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF |
-- AR_PHY_ANT_DIV_ALT_LNACONF |
-- AR_PHY_ANT_DIV_MAIN_GAINTB |
-- AR_PHY_ANT_DIV_ALT_GAINTB);
-- regval |= (AR_PHY_ANT_DIV_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S);
-- regval |= (AR_PHY_ANT_DIV_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S);
-+ regval &= ~AR_PHY_ANT_DIV_LNADIV;
-+ regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S;
-+ if (enable)
-+ regval |= AR_ANT_DIV_ENABLE;
-+
- REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
-+
-+ /*
-+ * Enable fast antenna diversity.
-+ */
-+ regval = REG_READ(ah, AR_PHY_CCK_DETECT);
-+ regval &= ~AR_FAST_DIV_ENABLE;
-+ regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
-+ if (enable)
-+ regval |= AR_FAST_DIV_ENABLE;
-+
-+ REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
-+
-+ if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
-+ regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
-+ regval &= (~(AR_PHY_ANT_DIV_MAIN_LNACONF |
-+ AR_PHY_ANT_DIV_ALT_LNACONF |
-+ AR_PHY_ANT_DIV_ALT_GAINTB |
-+ AR_PHY_ANT_DIV_MAIN_GAINTB));
-+ /*
-+ * Set MAIN to LNA1 and ALT to LNA2 at the
-+ * beginning.
-+ */
-+ regval |= (ATH_ANT_DIV_COMB_LNA1 <<
-+ AR_PHY_ANT_DIV_MAIN_LNACONF_S);
-+ regval |= (ATH_ANT_DIV_COMB_LNA2 <<
-+ AR_PHY_ANT_DIV_ALT_LNACONF_S);
-+ REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
-+ }
-+ } else if (AR_SREV_9565(ah)) {
-+ if (enable) {
-+ REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL,
-+ (1 << AR_PHY_ANT_SW_RX_PROT_S));
-+ if (ah->curchan && IS_CHAN_2GHZ(ah->curchan))
-+ REG_SET_BIT(ah, AR_PHY_RESTART,
-+ AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
-+ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
-+ AR_BTCOEX_WL_LNADIV_FORCE_ON);
-+ } else {
-+ REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE);
-+ REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
-+ (1 << AR_PHY_ANT_SW_RX_PROT_S));
-+ REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE);
-+ REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
-+ AR_BTCOEX_WL_LNADIV_FORCE_ON);
-+
-+ regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
-+ regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF |
-+ AR_PHY_ANT_DIV_ALT_LNACONF |
-+ AR_PHY_ANT_DIV_MAIN_GAINTB |
-+ AR_PHY_ANT_DIV_ALT_GAINTB);
-+ regval |= (ATH_ANT_DIV_COMB_LNA1 <<
-+ AR_PHY_ANT_DIV_MAIN_LNACONF_S);
-+ regval |= (ATH_ANT_DIV_COMB_LNA2 <<
-+ AR_PHY_ANT_DIV_ALT_LNACONF_S);
-+ REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
-+ }
- }
- }
-
-+#endif
-+
- static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
- struct ath9k_channel *chan,
- u8 *ini_reloaded)
-@@ -1518,6 +1567,18 @@ static int ar9003_hw_fast_chan_change(st
-
- REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
-
-+ if (AR_SREV_9462_20_OR_LATER(ah)) {
-+ /*
-+ * CUS217 mix LNA mode.
-+ */
-+ if (ar9003_hw_get_rx_gain_idx(ah) == 2) {
-+ REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core,
-+ 1, regWrites);
-+ REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
-+ modesIndex, regWrites);
-+ }
-+ }
-+
- /*
- * For 5GHz channels requiring Fast Clock, apply
- * different modal values.
-@@ -1528,7 +1589,11 @@ static int ar9003_hw_fast_chan_change(st
- if (AR_SREV_9565(ah))
- REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites);
-
-- REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
-+ /*
-+ * JAPAN regulatory.
-+ */
-+ if (chan->channel == 2484)
-+ ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
-
- ah->modes_index = modesIndex;
- *ini_reloaded = true;
-@@ -1631,11 +1696,14 @@ void ar9003_hw_attach_phy_ops(struct ath
-
- ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
- ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
-- ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv;
- ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
- ops->spectral_scan_trigger = ar9003_hw_spectral_scan_trigger;
- ops->spectral_scan_wait = ar9003_hw_spectral_scan_wait;
-
-+#ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-+ ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity;
-+#endif
-+
- ar9003_hw_set_nf_limits(ah);
- ar9003_hw_set_radar_conf(ah);
- memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_s
- struct ath_desc *ds;
- struct sk_buff *skb;
-
-- ATH_RXBUF_RESET(bf);
--
- ds = bf->bf_desc;
- ds->ds_link = 0; /* link to null */
- ds->ds_data = bf->bf_buf_addr;
-@@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_s
- sc->rx.rxlink = &ds->ds_link;
- }
-
-+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
-+{
-+ if (sc->rx.buf_hold)
-+ ath_rx_buf_link(sc, sc->rx.buf_hold);
-+
-+ sc->rx.buf_hold = bf;
-+}
-+
- static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
- {
- /* XXX block beacon interrupts */
-@@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct
-
- skb = bf->bf_mpdu;
-
-- ATH_RXBUF_RESET(bf);
- memset(skb->data, 0, ah->caps.rx_status_len);
- dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
- ah->caps.rx_status_len, DMA_TO_DEVICE);
-@@ -185,7 +190,7 @@ static void ath_rx_edma_cleanup(struct a
-
- static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
- {
-- skb_queue_head_init(&rx_edma->rx_fifo);
-+ __skb_queue_head_init(&rx_edma->rx_fifo);
- rx_edma->rx_fifo_hwsize = size;
- }
-
-@@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc)
- if (list_empty(&sc->rx.rxbuf))
- goto start_recv;
-
-+ sc->rx.buf_hold = NULL;
- sc->rx.rxlink = NULL;
- list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
- ath_rx_buf_link(sc, bf);
-@@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_b
- }
-
- bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
-+ if (bf == sc->rx.buf_hold)
-+ return NULL;
-+
- ds = bf->bf_desc;
-
- /*
-@@ -755,7 +764,6 @@ static bool ath9k_rx_accept(struct ath_c
- bool is_mc, is_valid_tkip, strip_mic, mic_error;
- struct ath_hw *ah = common->ah;
- __le16 fc;
-- u8 rx_status_len = ah->caps.rx_status_len;
-
- fc = hdr->frame_control;
-
-@@ -777,25 +785,6 @@ static bool ath9k_rx_accept(struct ath_c
- !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
- rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
-
-- if (!rx_stats->rs_datalen) {
-- RX_STAT_INC(rx_len_err);
-- return false;
-- }
--
-- /*
-- * rs_status follows rs_datalen so if rs_datalen is too large
-- * we can take a hint that hardware corrupted it, so ignore
-- * those frames.
-- */
-- if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) {
-- RX_STAT_INC(rx_len_err);
-- return false;
-- }
--
-- /* Only use error bits from the last fragment */
-- if (rx_stats->rs_more)
-- return true;
--
- mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
- !ieee80211_has_morefrags(fc) &&
- !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-@@ -814,8 +803,6 @@ static bool ath9k_rx_accept(struct ath_c
- rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
- mic_error = false;
- }
-- if (rx_stats->rs_status & ATH9K_RXERR_PHY)
-- return false;
-
- if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
- (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
-@@ -898,129 +885,65 @@ static int ath9k_process_rate(struct ath
-
- static void ath9k_process_rssi(struct ath_common *common,
- struct ieee80211_hw *hw,
-- struct ieee80211_hdr *hdr,
-- struct ath_rx_status *rx_stats)
-+ struct ath_rx_status *rx_stats,
-+ struct ieee80211_rx_status *rxs)
- {
- struct ath_softc *sc = hw->priv;
- struct ath_hw *ah = common->ah;
- int last_rssi;
- int rssi = rx_stats->rs_rssi;
-
-- if (!rx_stats->is_mybeacon ||
-- ((ah->opmode != NL80211_IFTYPE_STATION) &&
-- (ah->opmode != NL80211_IFTYPE_ADHOC)))
-+ /*
-+ * RSSI is not available for subframes in an A-MPDU.
-+ */
-+ if (rx_stats->rs_moreaggr) {
-+ rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
- return;
--
-- if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
-- ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
--
-- last_rssi = sc->last_rssi;
-- if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-- rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
-- if (rssi < 0)
-- rssi = 0;
--
-- /* Update Beacon RSSI, this is used by ANI. */
-- ah->stats.avgbrssi = rssi;
--}
--
--/*
-- * For Decrypt or Demic errors, we only mark packet status here and always push
-- * up the frame up to let mac80211 handle the actual error case, be it no
-- * decryption key or real decryption error. This let us keep statistics there.
-- */
--static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
-- struct ieee80211_hdr *hdr,
-- struct ath_rx_status *rx_stats,
-- struct ieee80211_rx_status *rx_status,
-- bool *decrypt_error)
--{
-- struct ieee80211_hw *hw = sc->hw;
-- struct ath_hw *ah = sc->sc_ah;
-- struct ath_common *common = ath9k_hw_common(ah);
-- bool discard_current = sc->rx.discard_next;
--
-- sc->rx.discard_next = rx_stats->rs_more;
-- if (discard_current)
-- return -EINVAL;
-+ }
-
- /*
-- * everything but the rate is checked here, the rate check is done
-- * separately to avoid doing two lookups for a rate for each frame.
-+ * Check if the RSSI for the last subframe in an A-MPDU
-+ * or an unaggregated frame is valid.
- */
-- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
-- return -EINVAL;
--
-- /* Only use status info from the last fragment */
-- if (rx_stats->rs_more)
-- return 0;
-+ if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
-+ rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
-+ return;
-+ }
-
-- if (ath9k_process_rate(common, hw, rx_stats, rx_status))
-- return -EINVAL;
-+ /*
-+ * Update Beacon RSSI, this is used by ANI.
-+ */
-+ if (rx_stats->is_mybeacon &&
-+ ((ah->opmode == NL80211_IFTYPE_STATION) ||
-+ (ah->opmode == NL80211_IFTYPE_ADHOC))) {
-+ ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
-+ last_rssi = sc->last_rssi;
-
-- ath9k_process_rssi(common, hw, hdr, rx_stats);
-+ if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-+ rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
-+ if (rssi < 0)
-+ rssi = 0;
-
-- rx_status->band = hw->conf.chandef.chan->band;
-- rx_status->freq = hw->conf.chandef.chan->center_freq;
-- rx_status->signal = ah->noise + rx_stats->rs_rssi;
-- rx_status->antenna = rx_stats->rs_antenna;
-- rx_status->flag |= RX_FLAG_MACTIME_END;
-- if (rx_stats->rs_moreaggr)
-- rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-+ ah->stats.avgbrssi = rssi;
-+ }
-
-- sc->rx.discard_next = false;
-- return 0;
-+ rxs->signal = ah->noise + rx_stats->rs_rssi;
- }
-
--static void ath9k_rx_skb_postprocess(struct ath_common *common,
-- struct sk_buff *skb,
-- struct ath_rx_status *rx_stats,
-- struct ieee80211_rx_status *rxs,
-- bool decrypt_error)
-+static void ath9k_process_tsf(struct ath_rx_status *rs,
-+ struct ieee80211_rx_status *rxs,
-+ u64 tsf)
- {
-- struct ath_hw *ah = common->ah;
-- struct ieee80211_hdr *hdr;
-- int hdrlen, padpos, padsize;
-- u8 keyix;
-- __le16 fc;
-+ u32 tsf_lower = tsf & 0xffffffff;
-
-- /* see if any padding is done by the hw and remove it */
-- hdr = (struct ieee80211_hdr *) skb->data;
-- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-- fc = hdr->frame_control;
-- padpos = ieee80211_hdrlen(fc);
-+ rxs->mactime = (tsf & ~0xffffffffULL) | rs->rs_tstamp;
-+ if (rs->rs_tstamp > tsf_lower &&
-+ unlikely(rs->rs_tstamp - tsf_lower > 0x10000000))
-+ rxs->mactime -= 0x100000000ULL;
-
-- /* The MAC header is padded to have 32-bit boundary if the
-- * packet payload is non-zero. The general calculation for
-- * padsize would take into account odd header lengths:
-- * padsize = (4 - padpos % 4) % 4; However, since only
-- * even-length headers are used, padding can only be 0 or 2
-- * bytes and we can optimize this a bit. In addition, we must
-- * not try to remove padding from short control frames that do
-- * not have payload. */
-- padsize = padpos & 3;
-- if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
-- memmove(skb->data + padsize, skb->data, padpos);
-- skb_pull(skb, padsize);
-- }
--
-- keyix = rx_stats->rs_keyix;
--
-- if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
-- ieee80211_has_protected(fc)) {
-- rxs->flag |= RX_FLAG_DECRYPTED;
-- } else if (ieee80211_has_protected(fc)
-- && !decrypt_error && skb->len >= hdrlen + 4) {
-- keyix = skb->data[hdrlen + 3] >> 6;
--
-- if (test_bit(keyix, common->keymap))
-- rxs->flag |= RX_FLAG_DECRYPTED;
-- }
-- if (ah->sw_mgmt_crypto &&
-- (rxs->flag & RX_FLAG_DECRYPTED) &&
-- ieee80211_is_mgmt(fc))
-- /* Use software decrypt for management frames. */
-- rxs->flag &= ~RX_FLAG_DECRYPTED;
-+ if (rs->rs_tstamp < tsf_lower &&
-+ unlikely(tsf_lower - rs->rs_tstamp > 0x10000000))
-+ rxs->mactime += 0x100000000ULL;
- }
-
- #ifdef CPTCFG_ATH9K_DEBUGFS
-@@ -1133,6 +1056,234 @@ static int ath_process_fft(struct ath_so
- #endif
- }
-
-+static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
-+{
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ath_common *common = ath9k_hw_common(ah);
-+
-+ if (ieee80211_is_beacon(hdr->frame_control)) {
-+ RX_STAT_INC(rx_beacons);
-+ if (!is_zero_ether_addr(common->curbssid) &&
-+ ether_addr_equal(hdr->addr3, common->curbssid))
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+/*
-+ * For Decrypt or Demic errors, we only mark packet status here and always push
-+ * up the frame up to let mac80211 handle the actual error case, be it no
-+ * decryption key or real decryption error. This let us keep statistics there.
-+ */
-+static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
-+ struct sk_buff *skb,
-+ struct ath_rx_status *rx_stats,
-+ struct ieee80211_rx_status *rx_status,
-+ bool *decrypt_error, u64 tsf)
-+{
-+ struct ieee80211_hw *hw = sc->hw;
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ struct ieee80211_hdr *hdr;
-+ bool discard_current = sc->rx.discard_next;
-+ int ret = 0;
-+
-+ /*
-+ * Discard corrupt descriptors which are marked in
-+ * ath_get_next_rx_buf().
-+ */
-+ sc->rx.discard_next = rx_stats->rs_more;
-+ if (discard_current)
-+ return -EINVAL;
-+
-+ /*
-+ * Discard zero-length packets.
-+ */
-+ if (!rx_stats->rs_datalen) {
-+ RX_STAT_INC(rx_len_err);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * rs_status follows rs_datalen so if rs_datalen is too large
-+ * we can take a hint that hardware corrupted it, so ignore
-+ * those frames.
-+ */
-+ if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
-+ RX_STAT_INC(rx_len_err);
-+ return -EINVAL;
-+ }
-+
-+ /* Only use status info from the last fragment */
-+ if (rx_stats->rs_more)
-+ return 0;
-+
-+ /*
-+ * Return immediately if the RX descriptor has been marked
-+ * as corrupt based on the various error bits.
-+ *
-+ * This is different from the other corrupt descriptor
-+ * condition handled above.
-+ */
-+ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
-+
-+ ath9k_process_tsf(rx_stats, rx_status, tsf);
-+ ath_debug_stat_rx(sc, rx_stats);
-+
-+ /*
-+ * Process PHY errors and return so that the packet
-+ * can be dropped.
-+ */
-+ if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
-+ ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime);
-+ if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
-+ RX_STAT_INC(rx_spectral);
-+
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ /*
-+ * everything but the rate is checked here, the rate check is done
-+ * separately to avoid doing two lookups for a rate for each frame.
-+ */
-+ if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
-+ if (rx_stats->is_mybeacon) {
-+ sc->hw_busy_count = 0;
-+ ath_start_rx_poll(sc, 3);
-+ }
-+
-+ if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
-+ ret =-EINVAL;
-+ goto exit;
-+ }
-+
-+ ath9k_process_rssi(common, hw, rx_stats, rx_status);
-+
-+ rx_status->band = hw->conf.chandef.chan->band;
-+ rx_status->freq = hw->conf.chandef.chan->center_freq;
-+ rx_status->antenna = rx_stats->rs_antenna;
-+ rx_status->flag |= RX_FLAG_MACTIME_END;
-+
-+#ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-+ if (ieee80211_is_data_present(hdr->frame_control) &&
-+ !ieee80211_is_qos_nullfunc(hdr->frame_control))
-+ sc->rx.num_pkts++;
-+#endif
-+
-+exit:
-+ sc->rx.discard_next = false;
-+ return ret;
-+}
-+
-+static void ath9k_rx_skb_postprocess(struct ath_common *common,
-+ struct sk_buff *skb,
-+ struct ath_rx_status *rx_stats,
-+ struct ieee80211_rx_status *rxs,
-+ bool decrypt_error)
-+{
-+ struct ath_hw *ah = common->ah;
-+ struct ieee80211_hdr *hdr;
-+ int hdrlen, padpos, padsize;
-+ u8 keyix;
-+ __le16 fc;
-+
-+ /* see if any padding is done by the hw and remove it */
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-+ fc = hdr->frame_control;
-+ padpos = ieee80211_hdrlen(fc);
-+
-+ /* The MAC header is padded to have 32-bit boundary if the
-+ * packet payload is non-zero. The general calculation for
-+ * padsize would take into account odd header lengths:
-+ * padsize = (4 - padpos % 4) % 4; However, since only
-+ * even-length headers are used, padding can only be 0 or 2
-+ * bytes and we can optimize this a bit. In addition, we must
-+ * not try to remove padding from short control frames that do
-+ * not have payload. */
-+ padsize = padpos & 3;
-+ if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
-+ memmove(skb->data + padsize, skb->data, padpos);
-+ skb_pull(skb, padsize);
-+ }
-+
-+ keyix = rx_stats->rs_keyix;
-+
-+ if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
-+ ieee80211_has_protected(fc)) {
-+ rxs->flag |= RX_FLAG_DECRYPTED;
-+ } else if (ieee80211_has_protected(fc)
-+ && !decrypt_error && skb->len >= hdrlen + 4) {
-+ keyix = skb->data[hdrlen + 3] >> 6;
-+
-+ if (test_bit(keyix, common->keymap))
-+ rxs->flag |= RX_FLAG_DECRYPTED;
-+ }
-+ if (ah->sw_mgmt_crypto &&
-+ (rxs->flag & RX_FLAG_DECRYPTED) &&
-+ ieee80211_is_mgmt(fc))
-+ /* Use software decrypt for management frames. */
-+ rxs->flag &= ~RX_FLAG_DECRYPTED;
-+}
-+
-+/*
-+ * Run the LNA combining algorithm only in these cases:
-+ *
-+ * Standalone WLAN cards with both LNA/Antenna diversity
-+ * enabled in the EEPROM.
-+ *
-+ * WLAN+BT cards which are in the supported card list
-+ * in ath_pci_id_table and the user has loaded the
-+ * driver with "bt_ant_diversity" set to true.
-+ */
-+static void ath9k_antenna_check(struct ath_softc *sc,
-+ struct ath_rx_status *rs)
-+{
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ath9k_hw_capabilities *pCap = &ah->caps;
-+ struct ath_common *common = ath9k_hw_common(ah);
-+
-+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB))
-+ return;
-+
-+ /*
-+ * All MPDUs in an aggregate will use the same LNA
-+ * as the first MPDU.
-+ */
-+ if (rs->rs_isaggr && !rs->rs_firstaggr)
-+ return;
-+
-+ /*
-+ * Change the default rx antenna if rx diversity
-+ * chooses the other antenna 3 times in a row.
-+ */
-+ if (sc->rx.defant != rs->rs_antenna) {
-+ if (++sc->rx.rxotherant >= 3)
-+ ath_setdefantenna(sc, rs->rs_antenna);
-+ } else {
-+ sc->rx.rxotherant = 0;
-+ }
-+
-+ if (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV) {
-+ if (common->bt_ant_diversity)
-+ ath_ant_comb_scan(sc, rs);
-+ } else {
-+ ath_ant_comb_scan(sc, rs);
-+ }
-+}
-+
- static void ath9k_apply_ampdu_details(struct ath_softc *sc,
- struct ath_rx_status *rs, struct ieee80211_rx_status *rxs)
- {
-@@ -1159,15 +1310,12 @@ int ath_rx_tasklet(struct ath_softc *sc,
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hw *hw = sc->hw;
-- struct ieee80211_hdr *hdr;
- int retval;
- struct ath_rx_status rs;
- enum ath9k_rx_qtype qtype;
- bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
- int dma_type;
-- u8 rx_status_len = ah->caps.rx_status_len;
- u64 tsf = 0;
-- u32 tsf_lower = 0;
- unsigned long flags;
- dma_addr_t new_buf_addr;
-
-@@ -1179,7 +1327,6 @@ int ath_rx_tasklet(struct ath_softc *sc,
- qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
-
- tsf = ath9k_hw_gettsf64(ah);
-- tsf_lower = tsf & 0xffffffff;
-
- do {
- bool decrypt_error = false;
-@@ -1206,55 +1353,14 @@ int ath_rx_tasklet(struct ath_softc *sc,
- else
- hdr_skb = skb;
-
-- hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
- rxs = IEEE80211_SKB_RXCB(hdr_skb);
-- if (ieee80211_is_beacon(hdr->frame_control)) {
-- RX_STAT_INC(rx_beacons);
-- if (!is_zero_ether_addr(common->curbssid) &&
-- ether_addr_equal(hdr->addr3, common->curbssid))
-- rs.is_mybeacon = true;
-- else
-- rs.is_mybeacon = false;
-- }
-- else
-- rs.is_mybeacon = false;
--
-- if (ieee80211_is_data_present(hdr->frame_control) &&
-- !ieee80211_is_qos_nullfunc(hdr->frame_control))
-- sc->rx.num_pkts++;
--
-- ath_debug_stat_rx(sc, &rs);
--
- memset(rxs, 0, sizeof(struct ieee80211_rx_status));
-
-- rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
-- if (rs.rs_tstamp > tsf_lower &&
-- unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
-- rxs->mactime -= 0x100000000ULL;
--
-- if (rs.rs_tstamp < tsf_lower &&
-- unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
-- rxs->mactime += 0x100000000ULL;
--
-- if (rs.rs_phyerr == ATH9K_PHYERR_RADAR)
-- ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
--
-- if (rs.rs_status & ATH9K_RXERR_PHY) {
-- if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
-- RX_STAT_INC(rx_spectral);
-- goto requeue_drop_frag;
-- }
-- }
--
-- retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
-- &decrypt_error);
-+ retval = ath9k_rx_skb_preprocess(sc, hdr_skb, &rs, rxs,
-+ &decrypt_error, tsf);
- if (retval)
- goto requeue_drop_frag;
-
-- if (rs.is_mybeacon) {
-- sc->hw_busy_count = 0;
-- ath_start_rx_poll(sc, 3);
-- }
- /* Ensure we always have an skb to requeue once we are done
- * processing the current buffer's skb */
- requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
-@@ -1308,8 +1414,6 @@ int ath_rx_tasklet(struct ath_softc *sc,
- sc->rx.frag = skb;
- goto requeue;
- }
-- if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
-- goto requeue_drop_frag;
-
- if (sc->rx.frag) {
- int space = skb->len - skb_tailroom(hdr_skb);
-@@ -1328,22 +1432,6 @@ int ath_rx_tasklet(struct ath_softc *sc,
- skb = hdr_skb;
- }
-
--
-- if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
--
-- /*
-- * change the default rx antenna if rx diversity
-- * chooses the other antenna 3 times in a row.
-- */
-- if (sc->rx.defant != rs.rs_antenna) {
-- if (++sc->rx.rxotherant >= 3)
-- ath_setdefantenna(sc, rs.rs_antenna);
-- } else {
-- sc->rx.rxotherant = 0;
-- }
--
-- }
--
- if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
- skb_trim(skb, skb->len - 8);
-
-@@ -1355,8 +1443,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
- ath_rx_ps(sc, skb, rs.is_mybeacon);
- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
-
-- if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
-- ath_ant_comb_scan(sc, &rs);
-+ ath9k_antenna_check(sc, &rs);
-
- ath9k_apply_ampdu_details(sc, &rs, rxs);
-
-@@ -1375,7 +1462,7 @@ requeue:
- if (edma) {
- ath_rx_edma_buf_link(sc, qtype);
- } else {
-- ath_rx_buf_link(sc, bf);
-+ ath_rx_buf_relink(sc, bf);
- ath9k_hw_rxena(ah);