]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-sta.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / wireless / iwlwifi / iwl-sta.c
index 7c7f7dcb1b1e190611a8134177966729cf04d60e..49493d176515b8f1a01509ac99ebb125e20482b0 100644 (file)
@@ -107,7 +107,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
        /*
         * XXX: The MAC address in the command buffer is often changed from
         * the original sent to the device. That is, the MAC address
-        * written to the command buffer often is not the same MAC adress
+        * written to the command buffer often is not the same MAC address
         * read from the command buffer when the command returns. This
         * issue has not yet been resolved and this debugging is left to
         * observe the problem.
@@ -400,7 +400,8 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
 }
 
 static int iwl_send_remove_station(struct iwl_priv *priv,
-                                  const u8 *addr, int sta_id)
+                                  const u8 *addr, int sta_id,
+                                  bool temporary)
 {
        struct iwl_rx_packet *pkt;
        int ret;
@@ -436,9 +437,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
        if (!ret) {
                switch (pkt->u.rem_sta.status) {
                case REM_STA_SUCCESS_MSK:
-                       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-                       iwl_sta_ucode_deactivate(priv, sta_id);
-                       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+                       if (!temporary) {
+                               spin_lock_irqsave(&priv->sta_lock, flags_spin);
+                               iwl_sta_ucode_deactivate(priv, sta_id);
+                               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+                       }
                        IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
                        break;
                default:
@@ -505,7 +508,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
 
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-       return iwl_send_remove_station(priv, addr, sta_id);
+       return iwl_send_remove_station(priv, addr, sta_id, false);
 out_err:
        spin_unlock_irqrestore(&priv->sta_lock, flags);
        return -EINVAL;
@@ -624,6 +627,49 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 }
 EXPORT_SYMBOL(iwl_restore_stations);
 
+void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+       unsigned long flags;
+       int sta_id = ctx->ap_sta_id;
+       int ret;
+       struct iwl_addsta_cmd sta_cmd;
+       struct iwl_link_quality_cmd lq;
+       bool active;
+
+       spin_lock_irqsave(&priv->sta_lock, flags);
+       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+               spin_unlock_irqrestore(&priv->sta_lock, flags);
+               return;
+       }
+
+       memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
+       sta_cmd.mode = 0;
+       memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
+
+       active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
+       priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+       spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+       if (active) {
+               ret = iwl_send_remove_station(
+                       priv, priv->stations[sta_id].sta.sta.addr,
+                       sta_id, true);
+               if (ret)
+                       IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
+                               priv->stations[sta_id].sta.sta.addr, ret);
+       }
+       spin_lock_irqsave(&priv->sta_lock, flags);
+       priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+       spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+       ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+       if (ret)
+               IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
+                       priv->stations[sta_id].sta.sta.addr, ret);
+       iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
+}
+EXPORT_SYMBOL(iwl_reprogram_ap_sta);
+
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
 {
        int i;
@@ -736,6 +782,14 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
        if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
                return -EINVAL;
 
+
+       spin_lock_irqsave(&priv->sta_lock, flags_spin);
+       if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
        iwl_dump_lq_cmd(priv, lq);
        BUG_ON(init && (cmd.flags & CMD_ASYNC));