]> Pileus Git - ~andy/linux/blobdiff - drivers/net/wireless/ath/ath9k/htc_drv_main.c
Merge tag 'sunxi-fixes-for-3.14' of https://github.com/mripard/linux into fixes
[~andy/linux] / drivers / net / wireless / ath / ath9k / htc_drv_main.c
index 608d739d13782233db4271f9248c3472601b1a5f..c9254a61ca52d0984c23efdf4cb01aeb6b40ae23 100644 (file)
@@ -1270,18 +1270,50 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
        mutex_unlock(&priv->mutex);
 }
 
+static void ath9k_htc_sta_rc_update_work(struct work_struct *work)
+{
+       struct ath9k_htc_sta *ista =
+           container_of(work, struct ath9k_htc_sta, rc_update_work);
+       struct ieee80211_sta *sta =
+           container_of((void *)ista, struct ieee80211_sta, drv_priv);
+       struct ath9k_htc_priv *priv = ista->htc_priv;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_target_rate trate;
+
+       mutex_lock(&priv->mutex);
+       ath9k_htc_ps_wakeup(priv);
+
+       memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
+       ath9k_htc_setup_rate(priv, sta, &trate);
+       if (!ath9k_htc_send_rate_cmd(priv, &trate))
+               ath_dbg(common, CONFIG,
+                       "Supported rates for sta: %pM updated, rate caps: 0x%X\n",
+                       sta->addr, be32_to_cpu(trate.capflags));
+       else
+               ath_dbg(common, CONFIG,
+                       "Unable to update supported rates for sta: %pM\n",
+                       sta->addr);
+
+       ath9k_htc_ps_restore(priv);
+       mutex_unlock(&priv->mutex);
+}
+
 static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
                             struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta)
 {
        struct ath9k_htc_priv *priv = hw->priv;
+       struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
        int ret;
 
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
        ret = ath9k_htc_add_station(priv, vif, sta);
-       if (!ret)
+       if (!ret) {
+               INIT_WORK(&ista->rc_update_work, ath9k_htc_sta_rc_update_work);
+               ista->htc_priv = priv;
                ath9k_htc_init_rate(priv, sta);
+       }
        ath9k_htc_ps_restore(priv);
        mutex_unlock(&priv->mutex);
 
@@ -1293,12 +1325,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
                                struct ieee80211_sta *sta)
 {
        struct ath9k_htc_priv *priv = hw->priv;
-       struct ath9k_htc_sta *ista;
+       struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
        int ret;
 
+       cancel_work_sync(&ista->rc_update_work);
+
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
-       ista = (struct ath9k_htc_sta *) sta->drv_priv;
        htc_sta_drain(priv->htc, ista->index);
        ret = ath9k_htc_remove_station(priv, vif, sta);
        ath9k_htc_ps_restore(priv);
@@ -1311,28 +1344,12 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    struct ieee80211_sta *sta, u32 changed)
 {
-       struct ath9k_htc_priv *priv = hw->priv;
-       struct ath_common *common = ath9k_hw_common(priv->ah);
-       struct ath9k_htc_target_rate trate;
-
-       mutex_lock(&priv->mutex);
-       ath9k_htc_ps_wakeup(priv);
+       struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
 
-       if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
-               memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
-               ath9k_htc_setup_rate(priv, sta, &trate);
-               if (!ath9k_htc_send_rate_cmd(priv, &trate))
-                       ath_dbg(common, CONFIG,
-                               "Supported rates for sta: %pM updated, rate caps: 0x%X\n",
-                               sta->addr, be32_to_cpu(trate.capflags));
-               else
-                       ath_dbg(common, CONFIG,
-                               "Unable to update supported rates for sta: %pM\n",
-                               sta->addr);
-       }
+       if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
+               return;
 
-       ath9k_htc_ps_restore(priv);
-       mutex_unlock(&priv->mutex);
+       schedule_work(&ista->rc_update_work);
 }
 
 static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,