ath9k_htc: Add support for bluetooth coexistence.
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / htc_drv_main.c
index e38ca66..5e318cb 100644 (file)
@@ -125,6 +125,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
        struct ieee80211_conf *conf = &common->hw->conf;
        bool fastcc = true;
        struct ieee80211_channel *channel = hw->conf.channel;
+       struct ath9k_hw_cal_data *caldata;
        enum htc_phymode mode;
        __be16 htc_mode;
        u8 cmd_rsp;
@@ -149,7 +150,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
                  priv->ah->curchan->channel,
                  channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf));
 
-       ret = ath9k_hw_reset(ah, hchan, fastcc);
+       caldata = &priv->caldata[channel->hw_value];
+       ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
        if (ret) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset channel (%u Mhz) "
@@ -364,7 +366,8 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
                caps = WLAN_RC_HT_FLAG;
                if (sta->ht_cap.mcs.rx_mask[1])
                        caps |= WLAN_RC_DS_FLAG;
-               if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+               if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
+                    (conf_is_ht40(&priv->hw->conf)))
                        caps |= WLAN_RC_40_FLAG;
                if (conf_is_ht40(&priv->hw->conf) &&
                    (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40))
@@ -438,10 +441,11 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
                          bss_conf->bssid, be32_to_cpu(trate.capflags));
 }
 
-int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
-                          struct ieee80211_vif *vif,
-                          struct ieee80211_sta *sta,
-                          enum ieee80211_ampdu_mlme_action action, u16 tid)
+static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
+                                 struct ieee80211_vif *vif,
+                                 struct ieee80211_sta *sta,
+                                 enum ieee80211_ampdu_mlme_action action,
+                                 u16 tid)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
        struct ath9k_htc_target_aggr aggr;
@@ -492,8 +496,7 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file)
 static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
                                   size_t count, loff_t *ppos)
 {
-       struct ath9k_htc_priv *priv =
-               (struct ath9k_htc_priv *) file->private_data;
+       struct ath9k_htc_priv *priv = file->private_data;
        struct ath9k_htc_target_stats cmd_rsp;
        char buf[512];
        unsigned int len = 0;
@@ -524,6 +527,9 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
        len += snprintf(buf + len, sizeof(buf) - len,
                        "%19s : %10u\n", "TX Rate", priv->debug.txrate);
 
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -536,8 +542,7 @@ static const struct file_operations fops_tgt_stats = {
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
                              size_t count, loff_t *ppos)
 {
-       struct ath9k_htc_priv *priv =
-               (struct ath9k_htc_priv *) file->private_data;
+       struct ath9k_htc_priv *priv = file->private_data;
        char buf[512];
        unsigned int len = 0;
 
@@ -570,6 +575,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
                        "%20s : %10u\n", "VO queued",
                        priv->debug.tx_stats.queue_stats[WME_AC_VO]);
 
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -582,8 +590,7 @@ static const struct file_operations fops_xmit = {
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
                              size_t count, loff_t *ppos)
 {
-       struct ath9k_htc_priv *priv =
-               (struct ath9k_htc_priv *) file->private_data;
+       struct ath9k_htc_priv *priv = file->private_data;
        char buf[512];
        unsigned int len = 0;
 
@@ -597,6 +604,9 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
                        "%20s : %10u\n", "SKBs Dropped",
                        priv->debug.rx_stats.skb_dropped);
 
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -1021,7 +1031,7 @@ static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
                ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
 
        /* Reset the HW */
-       ret = ath9k_hw_reset(ah, ah->curchan, false);
+       ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        if (ret) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset hardware; reset status %d "
@@ -1084,7 +1094,7 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
                ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
 
        /* Reset the HW */
-       ret = ath9k_hw_reset(ah, ah->curchan, false);
+       ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        if (ret) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset hardware; reset status %d "
@@ -1172,7 +1182,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
        ath9k_hw_configpcipowersave(ah, 0, 0);
 
        ath9k_hw_htc_resetinit(ah);
-       ret = ath9k_hw_reset(ah, init_channel, false);
+       ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
        if (ret) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset hardware; reset status %d "
@@ -1200,6 +1210,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 
        ieee80211_wake_queues(hw);
 
+       if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
+               ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                                          AR_STOMP_LOW_WLAN_WGHT);
+               ath9k_hw_btcoex_enable(ah);
+               ath_htc_resume_btcoex_work(priv);
+       }
        mutex_unlock(&priv->mutex);
 
        return ret;
@@ -1244,6 +1260,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
                                  "Monitor interface removed\n");
        }
 
+       if (ah->btcoex_hw.enabled) {
+               ath9k_hw_btcoex_disable(ah);
+               if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+                       ath_htc_cancel_btcoex_work(priv);
+       }
+
        ath9k_hw_phy_disable(ah);
        ath9k_hw_disable(ah);
        ath9k_hw_configpcipowersave(ah, 1, 1);
@@ -1575,9 +1597,10 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
                        key->hw_key_idx = ret;
                        /* push IV and Michael MIC generation to stack */
                        key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-                       if (key->alg == ALG_TKIP)
+                       if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
                                key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-                       if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+                       if (priv->ah->sw_mgmt_crypto &&
+                           key->cipher == WLAN_CIPHER_SUITE_CCMP)
                                key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
                        ret = 0;
                }