Search Linux Wireless

Re: [PATCH] d80211: Simplify channel & mode configuration

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

 



On Friday 09 February 2007 23:25, Michael Wu wrote:
> d80211: Simplify channel & mode configuration
>
Ok. Someday I'll stop revising my patches 15 minutes after I post them.

This is the same thing as before, except with even more code removed.

--

d80211: Simplify channel & mode configuration

This patch simplifies channel & mode setting while eliminating a race
between channel configuration and scanning. It also adds a call to
ieee80211_hw_config after ops->open.

Signed-off-by: Michael Wu <flamingice@xxxxxxxxxxxx>
---

 net/d80211/ieee80211.c       |   45 +++++++++++-----
 net/d80211/ieee80211_i.h     |    9 +--
 net/d80211/ieee80211_ioctl.c |   14 ++---
 net/d80211/ieee80211_sta.c   |  117 +++++-------------------------------------
 4 files changed, 53 insertions(+), 132 deletions(-)

diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 03d4028..c83520e 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2005,8 +2005,24 @@ int ieee80211_if_config_beacon(struct ne
 int ieee80211_hw_config(struct ieee80211_local *local)
 {
 	struct ieee80211_hw_mode *mode;
+	struct ieee80211_channel *chan;
 	int ret = 0;
 
+	if (local->sta_scanning) {
+		chan = local->scan_channel;
+		mode = local->scan_hw_mode;
+	} else {
+		chan = local->oper_channel;
+		mode = local->oper_hw_mode;
+	}
+
+	local->hw.conf.channel = chan->chan;
+	local->hw.conf.channel_val = chan->val;
+	local->hw.conf.power_level = chan->power_level;
+	local->hw.conf.freq = chan->freq;
+	local->hw.conf.phymode = mode->mode;
+	local->hw.conf.antenna_max = chan->antenna_max;
+
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 	printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
 	       "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
@@ -2016,16 +2032,11 @@ int ieee80211_hw_config(struct ieee80211
 	if (local->ops->config)
 		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
 
-	list_for_each_entry(mode, &local->modes_list, list) {
-		if (mode->mode == local->hw.conf.phymode) {
-			if (local->curr_rates != mode->rates)
-				rate_control_clear(local);
-			local->curr_rates = mode->rates;
-			local->num_curr_rates = mode->num_rates;
-			ieee80211_prepare_rates(local);
-			break;
-		}
-	}
+	if (local->curr_rates != mode->rates)
+		rate_control_clear(local);
+	local->curr_rates = mode->rates;
+	local->num_curr_rates = mode->num_rates;
+	ieee80211_prepare_rates(local);
 
 	return ret;
 }
@@ -2344,8 +2355,13 @@ static int ieee80211_open(struct net_dev
 			if (res) {
 				if (local->ops->stop)
 					local->ops->stop(local_to_hw(local));
-			} else if (local->apdev)
-				dev_open(local->apdev);
+			} else {
+				res = ieee80211_hw_config(local);
+				if (res && local->ops->stop)
+					local->ops->stop(local_to_hw(local));
+				else if (!res && local->apdev)
+					dev_open(local->apdev);
+			}
 		}
 		if (res) {
 			if (local->ops->remove_interface)
@@ -4711,12 +4727,11 @@ int ieee80211_register_hwmode(struct iee
 	if (!local->curr_rates) {
 		/* Default to this mode */
 		local->hw.conf.phymode = mode->mode;
+		local->oper_hw_mode = local->scan_hw_mode = mode;
+		local->oper_channel = local->scan_channel = &mode->channels[0];
 		local->curr_rates = mode->rates;
 		local->num_curr_rates = mode->num_rates;
 		ieee80211_prepare_rates(local);
-		local->hw.conf.freq = mode->channels[0].freq;
-		local->hw.conf.channel = mode->channels[0].chan;
-		local->hw.conf.channel_val = mode->channels[0].val;
 	}
 
 	ieee80211_init_client(local->mdev);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 9307882..60d0a22 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -435,18 +435,13 @@ struct ieee80211_local {
         spinlock_t sub_if_lock; /* mutex for STA data structures */
         struct list_head sub_if_list;
 	int sta_scanning;
-	struct ieee80211_hw_mode *scan_hw_mode;
 	int scan_channel_idx;
 	enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
 	unsigned long last_scan_completed;
 	struct delayed_work scan_work;
 	struct net_device *scan_dev;
-	int scan_oper_channel;
-	int scan_oper_channel_val;
-	int scan_oper_power_level;
-	int scan_oper_freq;
-	int scan_oper_phymode;
-	int scan_oper_antenna_max;
+	struct ieee80211_channel *oper_channel, *scan_channel;
+	struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
 	u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
 	size_t scan_ssid_len;
 	struct list_head sta_bss_list;
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 35d73f7..c7300cb 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1828,20 +1828,18 @@ int ieee80211_ioctl_siwfreq(struct net_d
 				if (set && mode->mode != local->next_mode)
 					continue;
 
-				local->hw.conf.channel = chan->chan;
-				local->hw.conf.channel_val = chan->val;
-                                local->hw.conf.power_level = chan->power_level;
-				local->hw.conf.freq = chan->freq;
-				local->hw.conf.phymode = mode->mode;
-                                local->hw.conf.antenna_max = chan->antenna_max;
+				local->oper_channel = chan;
+				local->oper_hw_mode = mode;
 				set++;
 			}
 		}
 	}
 
 	if (set) {
-		local->sta_scanning = 0; /* Abort possible scan */
-		return ieee80211_hw_config(local);
+		if (local->sta_scanning)
+			return 0;
+		else
+			return ieee80211_hw_config(local);
 	}
 
 	return -EINVAL;
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 57e7fa7..a883384 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -1401,19 +1401,12 @@ static void ieee80211_rx_bss_info(struct
 		struct ieee80211_rate *rates;
 		size_t num_rates;
 		u32 supp_rates, prev_rates;
-		int i, j, oper_mode;
-
-		rates = local->curr_rates;
-		num_rates = local->num_curr_rates;
-		oper_mode = local->sta_scanning ? local->scan_oper_phymode :
-			local->hw.conf.phymode;
-		list_for_each_entry(mode, &local->modes_list, list) {
-			if (oper_mode == mode->mode) {
-				rates = mode->rates;
-				num_rates = mode->num_rates;
-				break;
-			}
-		}
+		int i, j;
+
+		mode = local->sta_scanning ?
+		       local->scan_hw_mode : local->oper_hw_mode;
+		rates = mode->rates;
+		num_rates = mode->num_rates;
 
 		supp_rates = 0;
 		for (i = 0; i < elems.supp_rates_len +
@@ -1426,7 +1419,7 @@ static void ieee80211_rx_bss_info(struct
 				rate = elems.ext_supp_rates
 					[i - elems.supp_rates_len];
 			own_rate = 5 * (rate & 0x7f);
-			if (oper_mode == MODE_ATHEROS_TURBO)
+			if (mode->mode == MODE_ATHEROS_TURBO)
 				own_rate *= 2;
 			for (j = 0; j < num_rates; j++)
 				if (rates[j].rate == own_rate)
@@ -2011,29 +2004,6 @@ static void ieee80211_sta_new_auth(struc
 }
 
 
-static int ieee80211_ibss_allowed(struct ieee80211_local *local)
-{
-	struct ieee80211_hw_mode *mode;
-	int c;
-
-	list_for_each_entry(mode, &local->modes_list, list) {
-		if (mode->mode != local->hw.conf.phymode)
-			continue;
-		for (c = 0; c < mode->num_channels; c++) {
-			struct ieee80211_channel *chan = &mode->channels[c];
-			if (chan->flag & IEEE80211_CHAN_W_SCAN &&
-			    chan->chan == local->hw.conf.channel) {
-				if (chan->flag & IEEE80211_CHAN_W_IBSS)
-					return 1;
-				break;
-			}
-		}
-	}
-
-	return 0;
-}
-
-
 extern int ieee80211_ioctl_siwfreq(struct net_device *dev,
 				   struct iw_request_info *info,
 				   struct iw_freq *freq, char *extra);
@@ -2076,7 +2046,7 @@ static int ieee80211_sta_join_ibss(struc
 	rq.e = 1;
 	res = ieee80211_ioctl_siwfreq(dev, NULL, &rq, NULL);
 
-	if (!ieee80211_ibss_allowed(local)) {
+	if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) {
 		printk(KERN_DEBUG "%s: IBSS not allowed on channel %d "
 		       "(%d MHz)\n", dev->name, local->hw.conf.channel,
 		       local->hw.conf.freq);
@@ -2323,7 +2293,7 @@ static int ieee80211_sta_find_ibss(struc
 		if (time_after(jiffies, ifsta->ibss_join_req +
 			       IEEE80211_IBSS_JOIN_TIMEOUT)) {
 			if (ifsta->create_ibss &&
-			    ieee80211_ibss_allowed(local))
+			    local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
 				return ieee80211_sta_create_ibss(dev, ifsta);
 			if (ifsta->create_ibss) {
 				printk(KERN_DEBUG "%s: IBSS not allowed on the"
@@ -2445,54 +2415,6 @@ int ieee80211_sta_set_bssid(struct net_d
 }
 
 
-static void ieee80211_sta_save_oper_chan(struct net_device *dev)
-{
-	struct ieee80211_local *local = dev->ieee80211_ptr;
-	local->scan_oper_channel = local->hw.conf.channel;
-	local->scan_oper_channel_val = local->hw.conf.channel_val;
-	local->scan_oper_power_level = local->hw.conf.power_level;
-	local->scan_oper_freq = local->hw.conf.freq;
-	local->scan_oper_phymode = local->hw.conf.phymode;
-	local->scan_oper_antenna_max = local->hw.conf.antenna_max;
-}
-
-
-static int ieee80211_sta_restore_oper_chan(struct net_device *dev)
-{
-	struct ieee80211_local *local = dev->ieee80211_ptr;
-	local->hw.conf.channel = local->scan_oper_channel;
-	local->hw.conf.channel_val = local->scan_oper_channel_val;
-	local->hw.conf.power_level = local->scan_oper_power_level;
-	local->hw.conf.freq = local->scan_oper_freq;
-	local->hw.conf.phymode = local->scan_oper_phymode;
-	local->hw.conf.antenna_max = local->scan_oper_antenna_max;
-	return ieee80211_hw_config(local);
-}
-
-
-static int ieee80211_active_scan(struct ieee80211_local *local)
-{
-	struct ieee80211_hw_mode *mode;
-	int c;
-
-	list_for_each_entry(mode, &local->modes_list, list) {
-		if (mode->mode != local->hw.conf.phymode)
-			continue;
-		for (c = 0; c < mode->num_channels; c++) {
-			struct ieee80211_channel *chan = &mode->channels[c];
-			if (chan->flag & IEEE80211_CHAN_W_SCAN &&
-			    chan->chan == local->hw.conf.channel) {
-				if (chan->flag & IEEE80211_CHAN_W_ACTIVE_SCAN)
-					return 1;
-				break;
-			}
-		}
-	}
-
-	return 0;
-}
-
-
 void ieee80211_scan_completed(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
@@ -2505,6 +2427,10 @@ void ieee80211_scan_completed(struct iee
 	wmb();
 	local->sta_scanning = 0;
 
+	if (ieee80211_hw_config(local))
+		printk(KERN_DEBUG "%s: failed to restore operational"
+		       "channel after scan\n", dev->name);
+
 	memset(&wrqu, 0, sizeof(wrqu));
 	wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
 
@@ -2539,12 +2465,6 @@ void ieee80211_sta_scan_work(struct work
 		mode = local->scan_hw_mode;
 		if (local->scan_hw_mode->list.next == &local->modes_list &&
 		    local->scan_channel_idx >= mode->num_channels) {
-			if (ieee80211_sta_restore_oper_chan(dev)) {
-				printk(KERN_DEBUG "%s: failed to restore "
-				       "operational channel after scan\n",
-				       dev->name);
-			}
-
 			ieee80211_scan_completed(local_to_hw(local));
 			return;
 		}
@@ -2563,12 +2483,7 @@ void ieee80211_sta_scan_work(struct work
 			       dev->name, chan->chan, chan->freq);
 #endif
 
-			local->hw.conf.channel = chan->chan;
-			local->hw.conf.channel_val = chan->val;
-			local->hw.conf.power_level = chan->power_level;
-			local->hw.conf.freq = chan->freq;
-			local->hw.conf.phymode = mode->mode;
-			local->hw.conf.antenna_max = chan->antenna_max;
+			local->scan_channel = chan;
 			if (ieee80211_hw_config(local)) {
 				printk(KERN_DEBUG "%s: failed to set channel "
 				       "%d (%d MHz) for scan\n", dev->name,
@@ -2595,7 +2510,7 @@ void ieee80211_sta_scan_work(struct work
 		local->scan_state = SCAN_SEND_PROBE;
 		break;
 	case SCAN_SEND_PROBE:
-		if (ieee80211_active_scan(local)) {
+		if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
 			ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
 						 local->scan_ssid_len);
 			next_delay = IEEE80211_CHANNEL_TIME;
@@ -2656,8 +2571,6 @@ static int ieee80211_sta_start_scan(stru
 		return rc;
 	}
 
-	ieee80211_sta_save_oper_chan(dev);
-
 	local->sta_scanning = 1;
 	/* TODO: stop TX queue? */
 

Attachment: pgpAXClXkngmi.pgp
Description: PGP signature


[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