Search Linux Wireless

[PATCH/RFT] mac80211: try uploading key if a slot was freed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When we remove a key from hwaccel, that may mean
that there's a new free item in the hwaccel, and
we could fill it with another station's key. By
keeping track of which keys the driver said it
could not support (-EOPNOTSUPP) and which it had
no space for (-ENOSPC) we can try uploading a
key that was previously rejected due to no space
after another key is removed.

Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>
---
RFT because I really have no idea how to test this
properly. Maybe with a hacked driver that claims
to support only a single key in hwaccel?

 net/mac80211/key.c |   51 ++++++++++++++++++++++++++++++++++-----------------
 net/mac80211/key.h |    3 +++
 2 files changed, 37 insertions(+), 17 deletions(-)

--- wireless-testing.orig/net/mac80211/key.c	2009-08-07 16:48:46.000000000 +0200
+++ wireless-testing/net/mac80211/key.c	2009-08-07 16:59:01.000000000 +0200
@@ -141,20 +141,21 @@ static void ieee80211_key_enable_hw_acce
 
 	ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
 
-	if (!ret) {
-		spin_lock_bh(&todo_lock);
+	spin_lock_bh(&todo_lock);
+	if (!ret)
 		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
-		spin_unlock_bh(&todo_lock);
-	}
+	else if (ret == -EOPNOTSUPP)
+		key->flags |= KEY_FLAG_HWACCEL_NOT_SUPPORTED;
+	spin_unlock_bh(&todo_lock);
 
-	if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
-		printk(KERN_ERR "mac80211-%s: failed to set key "
-		       "(%d, %pM) to hardware (%d)\n",
-		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+	WARN(ret && ret != -ENOSPC && ret != -EOPNOTSUPP,
+	     "mac80211-%s: failed to set key (%d, %pM) to hardware (%d)\n",
+	     wiphy_name(key->local->hw.wiphy), key->conf.keyidx,
+	     sta ? sta->addr : bcast_addr, ret);
 }
 
-static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
+static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key,
+					   bool upload_another)
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_sta *sta;
@@ -184,14 +185,30 @@ static void ieee80211_key_disable_hw_acc
 	ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif,
 			  sta, &key->conf);
 
-	if (ret)
-		printk(KERN_ERR "mac80211-%s: failed to remove key "
-		       "(%d, %pM) from hardware (%d)\n",
-		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+	WARN(ret,
+	     "mac80211-%s: failed to remove key (%d, %pM) from hardware (%d)\n",
+	     wiphy_name(key->local->hw.wiphy), key->conf.keyidx,
+	     sta ? sta->addr : bcast_addr, ret);
 
 	spin_lock_bh(&todo_lock);
 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
+
+	list_for_each_entry(key, &sdata->key_list, list) {
+		if (key->flags & KEY_FLAG_HWACCEL_NOT_SUPPORTED)
+			continue;
+		if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
+			continue;
+		if (key->flags & KEY_FLAG_TODO_DELETE)
+			continue;
+		if (key->flags & KEY_FLAG_TODO_HWACCEL_ADD)
+			continue;
+		if (key->flags & KEY_FLAG_TODO_HWACCEL_REMOVE)
+			continue;
+		spin_unlock_bh(&todo_lock);
+		ieee80211_key_enable_hw_accel(key);
+		spin_lock_bh(&todo_lock);
+	}
+
 	spin_unlock_bh(&todo_lock);
 }
 
@@ -527,7 +544,7 @@ static void __ieee80211_key_destroy(stru
 	if (!key)
 		return;
 
-	ieee80211_key_disable_hw_accel(key);
+	ieee80211_key_disable_hw_accel(key, true);
 
 	if (key->conf.alg == ALG_CCMP)
 		ieee80211_aes_key_free(key->u.ccmp.tfm);
@@ -583,7 +600,7 @@ static void __ieee80211_key_todo(void)
 			work_done = true;
 		}
 		if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
-			ieee80211_key_disable_hw_accel(key);
+			ieee80211_key_disable_hw_accel(key, false);
 			work_done = true;
 		}
 		if (todoflags & KEY_FLAG_TODO_DELETE) {
--- wireless-testing.orig/net/mac80211/key.h	2009-08-07 16:49:17.000000000 +0200
+++ wireless-testing/net/mac80211/key.h	2009-08-07 16:58:47.000000000 +0200
@@ -48,6 +48,8 @@ struct sta_info;
  * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
  * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs
  *	to be updated.
+ * @KEY_FLAG_HWACCEL_NOT_SUPPORTED: hardware acceleration not supported for
+ *	this key type (tried and driver returned -EOPNOTSUPP)
  */
 enum ieee80211_internal_key_flags {
 	KEY_FLAG_UPLOADED_TO_HARDWARE	= BIT(0),
@@ -57,6 +59,7 @@ enum ieee80211_internal_key_flags {
 	KEY_FLAG_TODO_DEFKEY		= BIT(4),
 	KEY_FLAG_TODO_ADD_DEBUGFS	= BIT(5),
 	KEY_FLAG_TODO_DEFMGMTKEY	= BIT(6),
+	KEY_FLAG_HWACCEL_NOT_SUPPORTED	= BIT(7),
 };
 
 struct tkip_ctx {


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux