All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Buesch <mb@bu3sch.de>
To: Jiri Benc <jbenc@suse.cz>
Cc: John Linville <linville@tuxdriver.com>, linux-wireless@vger.kernel.org
Subject: [PATCH] mac80211: Allow sleeping in set_key op
Date: Sun, 6 May 2007 20:37:34 +0200	[thread overview]
Message-ID: <200705062037.35037.mb@bu3sch.de> (raw)

Allow drivers to sleep in the setkey function, as it's rather
complicated to defer set_key to a workqueue in the driver
(error code is lost, keyconf->hw_key_idx is possibly hard
to get right.)

Signed-off-by: Michael Buesch <mb@bu3sch.de>


Index: bu3sch-wireless-dev/net/mac80211/ieee80211_i.h
===================================================================
--- bu3sch-wireless-dev.orig/net/mac80211/ieee80211_i.h	2007-05-06 01:50:54.000000000 +0200
+++ bu3sch-wireless-dev/net/mac80211/ieee80211_i.h	2007-05-06 19:59:13.000000000 +0200
@@ -420,7 +420,6 @@ struct ieee80211_local {
 	spinlock_t sta_lock; /* mutex for STA data structures */
 	int num_sta; /* number of stations in sta_list */
 	struct list_head sta_list;
-	struct list_head deleted_sta_list;
 	struct sta_info *sta_hash[STA_HASH_SIZE];
 	struct timer_list sta_cleanup;
 
Index: bu3sch-wireless-dev/net/mac80211/sta_info.c
===================================================================
--- bu3sch-wireless-dev.orig/net/mac80211/sta_info.c	2007-05-06 01:50:54.000000000 +0200
+++ bu3sch-wireless-dev/net/mac80211/sta_info.c	2007-05-06 20:22:20.000000000 +0200
@@ -193,9 +193,42 @@ struct sta_info * sta_info_add(struct ie
 	return sta;
 }
 
+
+static void sta_info_key_disable(struct ieee80211_local *local,
+				 struct sta_info *sta)
+{
+	might_sleep();
+	if (sta->key) {
+		if (local->ops->set_key) {
+			struct ieee80211_key_conf *key;
+			key = ieee80211_key_data2conf(local, sta->key);
+			if (key) {
+				local->ops->set_key(local_to_hw(local),
+						   DISABLE_KEY,
+						   sta->addr, key, sta->aid);
+				kfree(key);
+			}
+		}
+	} else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
+		struct ieee80211_key_conf conf;
+		memset(&conf, 0, sizeof(conf));
+		conf.hw_key_idx = sta->key_idx_compression;
+		conf.alg = ALG_NULL;
+		conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
+		if (local->ops->set_key) {
+			local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+					    sta->addr, &conf, sta->aid);
+		}
+		sta->key_idx_compression = HW_KEY_IDX_INVALID;
+	}
+}
+
+
 static void finish_sta_info_free(struct ieee80211_local *local,
 				 struct sta_info *sta)
 {
+	sta_info_key_disable(local, sta);
+
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 	printk(KERN_DEBUG "%s: Removed STA " MAC_FMT "\n",
 	       local->mdev->name, MAC_ARG(sta->addr));
@@ -213,6 +246,16 @@ static void finish_sta_info_free(struct 
 	sta_info_put(sta);
 }
 
+
+static void finish_sta_info_free_work(struct work_struct *work)
+{
+	struct sta_info *sta =
+		container_of(work, struct sta_info, finish_free_work);
+
+	finish_sta_info_free(sta->local, sta);
+}
+
+
 static void sta_info_remove(struct sta_info *sta)
 {
 	struct ieee80211_local *local = sta->local;
@@ -230,6 +273,7 @@ static void sta_info_remove(struct sta_i
 	sta_info_remove_aid_ptr(sta);
 }
 
+
 void sta_info_free(struct sta_info *sta, int locked)
 {
 	struct sk_buff *skb;
@@ -254,34 +298,11 @@ void sta_info_free(struct sta_info *sta,
 		dev_kfree_skb_any(skb);
 	}
 
-	if (sta->key) {
-		if (local->ops->set_key) {
-			struct ieee80211_key_conf *key;
-			key = ieee80211_key_data2conf(local, sta->key);
-			if (key) {
-				local->ops->set_key(local_to_hw(local),
-						   DISABLE_KEY,
-						   sta->addr, key, sta->aid);
-				kfree(key);
-			}
-		}
-	} else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
-		struct ieee80211_key_conf conf;
-		memset(&conf, 0, sizeof(conf));
-		conf.hw_key_idx = sta->key_idx_compression;
-		conf.alg = ALG_NULL;
-		conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
-		local->ops->set_key(local_to_hw(local), DISABLE_KEY,
-				   sta->addr, &conf, sta->aid);
-		sta->key_idx_compression = HW_KEY_IDX_INVALID;
-	}
-
-#ifdef CONFIG_MAC80211_DEBUGFS
 	if (in_atomic()) {
-		list_add(&sta->list, &local->deleted_sta_list);
-		queue_work(local->hw.workqueue, &local->sta_debugfs_add);
+		/* Schedule the finishing to be able to sleep. */
+		INIT_WORK(&sta->finish_free_work, finish_sta_info_free_work);
+		queue_work(local->hw.workqueue, &sta->finish_free_work);
 	} else
-#endif
 		finish_sta_info_free(local, sta);
 }
 
@@ -363,20 +384,6 @@ static void sta_info_debugfs_add_task(st
 	struct sta_info *sta, *tmp;
 
 	while (1) {
-		spin_lock_bh(&local->sta_lock);
-		if (!list_empty(&local->deleted_sta_list)) {
-			sta = list_entry(local->deleted_sta_list.next,
-					 struct sta_info, list);
-			list_del(local->deleted_sta_list.next);
-		} else
-			sta = NULL;
-		spin_unlock_bh(&local->sta_lock);
-		if (!sta)
-			break;
-		finish_sta_info_free(local, sta);
-	}
-
-	while (1) {
 		sta = NULL;
 		spin_lock_bh(&local->sta_lock);
 		list_for_each_entry(tmp, &local->sta_list, list) {
@@ -403,7 +410,6 @@ void sta_info_init(struct ieee80211_loca
 {
 	spin_lock_init(&local->sta_lock);
 	INIT_LIST_HEAD(&local->sta_list);
-	INIT_LIST_HEAD(&local->deleted_sta_list);
 
 	init_timer(&local->sta_cleanup);
 	local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
Index: bu3sch-wireless-dev/net/mac80211/sta_info.h
===================================================================
--- bu3sch-wireless-dev.orig/net/mac80211/sta_info.h	2007-05-06 01:50:54.000000000 +0200
+++ bu3sch-wireless-dev/net/mac80211/sta_info.h	2007-05-06 19:58:58.000000000 +0200
@@ -133,6 +133,8 @@ struct sta_info {
 #endif
 	} debugfs;
 #endif
+
+	struct work_struct finish_free_work;
 };
 
 
Index: bu3sch-wireless-dev/include/net/mac80211.h
===================================================================
--- bu3sch-wireless-dev.orig/include/net/mac80211.h	2007-05-01 22:32:36.000000000 +0200
+++ bu3sch-wireless-dev/include/net/mac80211.h	2007-05-06 20:29:26.000000000 +0200
@@ -620,8 +620,7 @@ struct ieee80211_ops {
 	 * station hwaddr for individual keys. aid of the station is given
 	 * to help low-level driver in selecting which key->hw_key_idx to use
 	 * for this key. TX control data will use the hw_key_idx selected by
-	 * the low-level driver.
-	 * Must be atomic. */
+	 * the low-level driver. */
 	int (*set_key)(struct ieee80211_hw *hw, set_key_cmd cmd,
 		       u8 *addr, struct ieee80211_key_conf *key, int aid);
 

-- 
Greetings Michael.

             reply	other threads:[~2007-05-06 18:39 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-06 18:37 Michael Buesch [this message]
2007-05-07 16:52 ` [PATCH] mac80211: Allow sleeping in set_key op Jiri Benc
2007-05-07 20:44   ` Michael Buesch
2007-05-14 17:37     ` Jiri Benc
2007-05-14 17:47       ` Michael Buesch
2007-05-07 19:17 ` Michael Wu
2007-05-07 20:50   ` Michael Buesch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200705062037.35037.mb@bu3sch.de \
    --to=mb@bu3sch.de \
    --cc=jbenc@suse.cz \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.