]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/mac80211/key.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx
[linux-2.6-omap-h63xx.git] / net / mac80211 / key.c
index acf8d0370a3716607a690580894ef5ced08e9bc4..6597c779e35a946147c510b5f0659afb4b40bce7 100644 (file)
@@ -74,9 +74,12 @@ static void add_todo(struct ieee80211_key *key, u32 flag)
 
        spin_lock(&todo_lock);
        key->flags |= flag;
-       /* only add if not already added */
-       if (list_empty(&key->todo))
-               list_add(&key->todo, &todo_list);
+       /*
+        * Remove again if already on the list so that we move it to the end.
+        */
+       if (!list_empty(&key->todo))
+               list_del(&key->todo);
+       list_add_tail(&key->todo, &todo_list);
        schedule_work(&todo_work);
        spin_unlock(&todo_lock);
 }
@@ -210,9 +213,9 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&sdata->local->sta_lock, flags);
+       spin_lock_irqsave(&sdata->local->key_lock, flags);
        __ieee80211_set_default_key(sdata, idx);
-       spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
+       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
 }
 
 
@@ -318,8 +321,15 @@ void ieee80211_key_link(struct ieee80211_key *key,
                 * some hardware cannot handle TKIP with QoS, so
                 * we indicate whether QoS could be in use.
                 */
-               if (sta->flags & WLAN_STA_WME)
+               if (test_sta_flags(sta, WLAN_STA_WME))
                        key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
+
+               /*
+                * This key is for a specific sta interface,
+                * inform the driver that it should try to store
+                * this key as pairwise key.
+                */
+               key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
        } else {
                if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
                        struct sta_info *ap;
@@ -332,14 +342,14 @@ void ieee80211_key_link(struct ieee80211_key *key,
                        /* same here, the AP could be using QoS */
                        ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
                        if (ap) {
-                               if (ap->flags & WLAN_STA_WME)
+                               if (test_sta_flags(ap, WLAN_STA_WME))
                                        key->conf.flags |=
                                                IEEE80211_KEY_FLAG_WMM_STA;
                        }
                }
        }
 
-       spin_lock_irqsave(&sdata->local->sta_lock, flags);
+       spin_lock_irqsave(&sdata->local->key_lock, flags);
 
        if (sta)
                old_key = sta->key;
@@ -348,7 +358,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
 
        __ieee80211_key_replace(sdata, sta, old_key, key);
 
-       spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
+       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
 
        /* free old key later */
        add_todo(old_key, KEY_FLAG_TODO_DELETE);
@@ -377,9 +387,18 @@ void ieee80211_key_free(struct ieee80211_key *key)
        if (!key)
                return;
 
-       spin_lock_irqsave(&key->sdata->local->sta_lock, flags);
+       if (!key->sdata) {
+               /* The key has not been linked yet, simply free it
+                * and don't Oops */
+               if (key->conf.alg == ALG_CCMP)
+                       ieee80211_aes_key_free(key->u.ccmp.tfm);
+               kfree(key);
+               return;
+       }
+
+       spin_lock_irqsave(&key->sdata->local->key_lock, flags);
        __ieee80211_key_free(key);
-       spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags);
+       spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
 }
 
 /*
@@ -397,10 +416,10 @@ static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
 
        might_sleep();
 
-       spin_lock_irqsave(&sdata->local->sta_lock, flags);
+       spin_lock_irqsave(&sdata->local->key_lock, flags);
        list_for_each_entry(key, &sdata->key_list, list)
                add_todo(key, todo_flags);
-       spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
+       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
 
        ieee80211_key_todo();
 }
@@ -506,10 +525,10 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
 
        ieee80211_debugfs_key_remove_default(sdata);
 
-       spin_lock_irqsave(&sdata->local->sta_lock, flags);
+       spin_lock_irqsave(&sdata->local->key_lock, flags);
        list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
                __ieee80211_key_free(key);
-       spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
+       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
 
        __ieee80211_key_todo();