ath9k_htc: accept firmware versions newer than 1.3
[openwrt.git] / package / mac80211 / patches / 300-pending_work.patch
index 9154d55bc1dc149fbd39535b0525e52be5a955a7..7558c3d1a2ff35d3357b3a467ae50b8e9bd6433b 100644 (file)
                            TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
 --- a/net/mac80211/iface.c
 +++ b/net/mac80211/iface.c
+@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct iee
+               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
+ }
+-static u32 ieee80211_idle_off(struct ieee80211_local *local)
++u32 ieee80211_idle_off(struct ieee80211_local *local)
+ {
+       if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
+               return 0;
 @@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80
  
        lockdep_assert_held(&local->mtx);
  static void ieee80211_iface_work(struct work_struct *work)
  {
        struct ieee80211_sub_if_data *sdata =
-@@ -1126,6 +1175,9 @@ static void ieee80211_iface_work(struct
+@@ -1126,6 +1175,9 @@ static void ieee80211_iface_work(struct 
                                break;
                        ieee80211_mesh_rx_queued_mgmt(sdata, skb);
                        break;
  
  #define CCK_ACK_DURATION(_bitrate, _short)                    \
        (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) +   \
-@@ -211,7 +211,8 @@ static void
+@@ -211,20 +211,32 @@ static void
  minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
  {
        struct minstrel_rate_stats *mr;
 -      unsigned int usecs = 0;
 +      unsigned int nsecs = 0;
 +      unsigned int tp;
++      unsigned int prob;
  
        mr = &mi->groups[group].rates[rate];
++      prob = mr->probability;
  
-@@ -221,10 +222,12 @@ minstrel_ht_calc_tp(struct minstrel_ht_s
+-      if (mr->probability < MINSTREL_FRAC(1, 10)) {
++      if (prob < MINSTREL_FRAC(1, 10)) {
+               mr->cur_tp = 0;
+               return;
        }
  
++      /*
++       * For the throughput calculation, limit the probability value to 90% to
++       * account for collision related packet error rate fluctuation
++       */
++      if (prob > MINSTREL_FRAC(9, 10))
++              prob = MINSTREL_FRAC(9, 10);
++
        if (group != MINSTREL_CCK_GROUP)
 -              usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
 +              nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
  }
  
  /*
-@@ -308,8 +311,8 @@ minstrel_ht_update_stats(struct minstrel
+@@ -308,8 +320,8 @@ minstrel_ht_update_stats(struct minstrel
                }
        }
  
  
        cur_prob = 0;
        cur_prob_tp = 0;
-@@ -320,20 +323,13 @@ minstrel_ht_update_stats(struct minstrel
+@@ -320,20 +332,13 @@ minstrel_ht_update_stats(struct minstrel
                if (!mg->supported)
                        continue;
  
                }
  
                mr = minstrel_get_ratestats(mi, mg->max_tp_rate2);
-@@ -343,6 +339,23 @@ minstrel_ht_update_stats(struct minstrel
+@@ -343,6 +348,23 @@ minstrel_ht_update_stats(struct minstrel
                }
        }
  
        mi->stats_update = jiffies;
  }
  
-@@ -467,7 +480,7 @@ minstrel_ht_tx_status(void *priv, struct
+@@ -467,7 +489,7 @@ minstrel_ht_tx_status(void *priv, struct
  
        if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
                mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
                mi->sample_count--;
        }
  
-@@ -536,7 +549,7 @@ minstrel_calc_retransmit(struct minstrel
+@@ -536,7 +558,7 @@ minstrel_calc_retransmit(struct minstrel
        mr->retry_updated = true;
  
        group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
  
        /* Contention time for first 2 tries */
        ctime = (t_slot * cw) >> 1;
-@@ -616,6 +629,7 @@ minstrel_get_sample_rate(struct minstrel
+@@ -616,6 +638,7 @@ minstrel_get_sample_rate(struct minstrel
  {
        struct minstrel_rate_stats *mr;
        struct minstrel_mcs_group_data *mg;
        int sample_idx = 0;
  
        if (mi->sample_wait > 0) {
-@@ -626,11 +640,11 @@ minstrel_get_sample_rate(struct minstrel
+@@ -626,39 +649,46 @@ minstrel_get_sample_rate(struct minstrel
        if (!mi->sample_tries)
                return -1;
  
        minstrel_next_sample_idx(mi);
  
        /*
-@@ -651,14 +665,18 @@ minstrel_get_sample_rate(struct minstrel
+        * Sampling might add some overhead (RTS, no aggregation)
+        * to the frame. Hence, don't use sampling for the currently
+-       * used max TP rate.
++       * used rates.
+        */
+-      if (sample_idx == mi->max_tp_rate)
++      if (sample_idx == mi->max_tp_rate ||
++          sample_idx == mi->max_tp_rate2 ||
++          sample_idx == mi->max_prob_rate)
+               return -1;
++
+       /*
+-       * When not using MRR, do not sample if the probability is already
+-       * higher than 95% to avoid wasting airtime
++       * Do not sample if the probability is already higher than 95%
++       * to avoid wasting airtime.
+        */
+-      if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
++      if (mr->probability > MINSTREL_FRAC(95, 100))
+               return -1;
+       /*
         * Make sure that lower rates get sampled only occasionally,
         * if the link is working perfectly.
         */
  
        /* time of last status update */
        unsigned long stats_update;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct at
+                                         AR_PHY_AGC_CONTROL_FLTR_CAL   |
+                                         AR_PHY_AGC_CONTROL_PKDET_CAL;
++      /* Use chip chainmask only for calibration */
+       ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+       if (rtt) {
+@@ -1150,6 +1151,9 @@ skip_tx_iqcal:
+               ar9003_hw_rtt_disable(ah);
+       }
++      /* Revert chainmask to runtime parameters */
++      ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
++
+       /* Initialize list pointers */
+       ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -3606,6 +3606,12 @@ static void ar9003_hw_ant_ctrl_apply(str
+       value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
+       REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
++      if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
++              value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
++              REG_RMW_FIELD(ah, switch_chain_reg[0],
++                            AR_SWITCH_TABLE_ALL, value);
++      }
++
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+               if ((ah->rxchainmask & BIT(chain)) ||
+                   (ah->txchainmask & BIT(chain))) {
+@@ -3772,6 +3778,17 @@ static void ar9003_hw_atten_apply(struct
+                                         AR_PHY_EXT_ATTEN_CTL_2,
+                                        };
++      if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
++              value = ar9003_hw_atten_chain_get(ah, 1, chan);
++              REG_RMW_FIELD(ah, ext_atten_reg[0],
++                            AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
++
++              value = ar9003_hw_atten_chain_get_margin(ah, 1, chan);
++              REG_RMW_FIELD(ah, ext_atten_reg[0],
++                            AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
++                            value);
++      }
++
+       /* Test value. if 0 then attenuation is unused. Don't load anything. */
+       for (i = 0; i < 3; i++) {
+               if (ah->txchainmask & BIT(i)) {
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct wo
+       int i;
+       bool needreset = false;
+-      for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+-              if (ATH_TXQ_SETUP(sc, i)) {
+-                      txq = &sc->tx.txq[i];
+-                      ath_txq_lock(sc, txq);
+-                      if (txq->axq_depth) {
+-                              if (txq->axq_tx_inprogress) {
+-                                      needreset = true;
+-                                      ath_txq_unlock(sc, txq);
+-                                      break;
+-                              } else {
+-                                      txq->axq_tx_inprogress = true;
+-                              }
++      for (i = 0; i < IEEE80211_NUM_ACS; i++) {
++              txq = sc->tx.txq_map[i];
++
++              ath_txq_lock(sc, txq);
++              if (txq->axq_depth) {
++                      if (txq->axq_tx_inprogress) {
++                              needreset = true;
++                              ath_txq_unlock(sc, txq);
++                              break;
++                      } else {
++                              txq->axq_tx_inprogress = true;
+                       }
+-                      ath_txq_unlock_complete(sc, txq);
+               }
++              ath_txq_unlock_complete(sc, txq);
++      }
+       if (needreset) {
+               ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -766,6 +766,7 @@ int __must_check __sta_info_destroy(stru
+       struct ieee80211_local *local;
+       struct ieee80211_sub_if_data *sdata;
+       int ret, i;
++      bool have_key = false;
+       might_sleep();
+@@ -793,12 +794,19 @@ int __must_check __sta_info_destroy(stru
+       list_del_rcu(&sta->list);
+       mutex_lock(&local->key_mtx);
+-      for (i = 0; i < NUM_DEFAULT_KEYS; i++)
++      for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+               __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
+-      if (sta->ptk)
++              have_key = true;
++      }
++      if (sta->ptk) {
+               __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
++              have_key = true;
++      }
+       mutex_unlock(&local->key_mtx);
++      if (!have_key)
++              synchronize_net();
++
+       sta->dead = true;
+       local->num_sta--;
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_l
+                     enum ieee80211_chanctx_mode mode)
+ {
+       struct ieee80211_chanctx *ctx;
++      u32 changed;
+       int err;
+       lockdep_assert_held(&local->chanctx_mtx);
+@@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_l
+       ctx->conf.rx_chains_dynamic = 1;
+       ctx->mode = mode;
++      /* acquire mutex to prevent idle from changing */
++      mutex_lock(&local->mtx);
++      /* turn idle off *before* setting channel -- some drivers need that */
++      changed = ieee80211_idle_off(local);
++      if (changed)
++              ieee80211_hw_config(local, changed);
++
+       if (!local->use_chanctx) {
+               local->_oper_channel_type =
+                       cfg80211_get_chandef_type(chandef);
+@@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_l
+               err = drv_add_chanctx(local, ctx);
+               if (err) {
+                       kfree(ctx);
+-                      return ERR_PTR(err);
++                      ctx = ERR_PTR(err);
++
++                      ieee80211_recalc_idle(local);
++                      goto out;
+               }
+       }
++      /* and keep the mutex held until the new chanctx is on the list */
+       list_add_rcu(&ctx->list, &local->chanctx_list);
+-      mutex_lock(&local->mtx);
+-      ieee80211_recalc_idle(local);
++ out:
+       mutex_unlock(&local->mtx);
+       return ctx;
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1366,6 +1366,7 @@ int ieee80211_if_change_type(struct ieee
+                            enum nl80211_iftype type);
+ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_remove_interfaces(struct ieee80211_local *local);
++u32 ieee80211_idle_off(struct ieee80211_local *local);
+ void ieee80211_recalc_idle(struct ieee80211_local *local);
+ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
+                                   const int offset);
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -799,7 +799,7 @@ static int ath9k_init_firmware_version(s
+        * required version.
+        */
+       if (priv->fw_version_major != MAJOR_VERSION_REQ ||
+-          priv->fw_version_minor != MINOR_VERSION_REQ) {
++          priv->fw_version_minor < MINOR_VERSION_REQ) {
+               dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
+                       MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
+               return -EINVAL;