netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
  2006-12-16  6:40 ` Michael Wu
@ 2000-01-01  0:23   ` Michael Buesch
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Buesch @ 2000-01-01  0:23 UTC (permalink / raw)
  To: Michael Wu; +Cc: jbenc, linville, netdev, bcm43xx-dev

On Saturday 16 December 2006 07:40, Michael Wu wrote:
> On Thursday 14 December 2006 13:20, Michael Buesch wrote:
> > -int ieee80211_update_hw(struct ieee80211_hw *hw)
> > +int ieee80211_register_hwmode(struct ieee80211_hw *hw,
> > +			      struct ieee80211_hw_mode *mode)
> Looks like this function never returns nonzero now. Can it return void 
> instead? This would simplify the fixes for drivers a bit.

Well, theoretically, yes.
Maybe it's only my personal way to do things, but I usually
let such API register functions return an error code, because
if we internally change it only slightly, it often turns out
we need an error code. For example let's say we need to
kmalloc something in that function for some reason.

If you say, well, breaking the API again is ok, when this is required,
send a patch. ;)

-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
@ 2006-12-14 18:20 Michael Buesch
  2006-12-15 13:48 ` Jiri Benc
  2006-12-16  6:40 ` Michael Wu
  0 siblings, 2 replies; 8+ messages in thread
From: Michael Buesch @ 2006-12-14 18:20 UTC (permalink / raw)
  To: jbenc-AlSwsSmVLrQ
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linville-2XuSBdqkA4R54TAoqtyWWQ,
	mb-fseUSCV1ubazQB+pC5nmwQ, bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w

This turns the PHY-modes list into a linked list.
The advantage is that drivers can add modes dynamically, as they probe
them and don't have to settle to a given arraysize at the beginning
of probing.

Signed-off-by: Michael Buesch <mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>

--

Note that I will also send fixup patches for all other d80211 drivers,
if no complaints are done against this patch.

Index: bu3sch-wireless-dev/include/net/d80211.h
===================================================================
--- bu3sch-wireless-dev.orig/include/net/d80211.h	2006-12-05 
18:09:34.000000000 +0100
+++ bu3sch-wireless-dev/include/net/d80211.h	2006-12-13 19:40:05.000000000 
+0100
@@ -76,12 +76,14 @@ struct ieee80211_rate {
 		       * optimizing channel utilization estimates */
 };
 
-struct ieee80211_hw_modes {
-	int mode;
-	int num_channels;
-	struct ieee80211_channel *channels;
-	int num_rates;
-        struct ieee80211_rate *rates;
+struct ieee80211_hw_mode {
+	int mode; /* MODE_IEEE80211... */
+	int num_channels; /* Number of channels (below) */
+	struct ieee80211_channel *channels; /* Array of supported channels */
+	int num_rates; /* Number of rates (below) */
+        struct ieee80211_rate *rates; /* Array of supported rates */
+
+	struct list_head list; /* Internal, don't touch */
 };
 
 struct ieee80211_tx_queue_params {
@@ -420,9 +422,7 @@ typedef enum {
 	SET_KEY, DISABLE_KEY, REMOVE_ALL_KEYS,
 } set_key_cmd;
 
-/* This is driver-visible part of the per-hw state the stack keeps.
- * If you change something in here, call ieee80211_update_hw() to
- * notify the stack about the change. */
+/* This is driver-visible part of the per-hw state the stack keeps. */
 struct ieee80211_hw {
 	/* these are assigned by d80211, don't write */
 	int index;
@@ -512,9 +512,6 @@ struct ieee80211_hw {
 	/* This is maximum value for rssi reported by this device */
 	int maxssi;
 
-	int num_modes;
-	struct ieee80211_hw_modes *modes;
-
 	/* Number of available hardware TX queues for data packets.
 	 * WMM requires at least four queues. */
 	int queues;
@@ -750,9 +747,9 @@ static inline char *ieee80211_get_rx_led
 #endif
 }
 
-/* Call this function if you changed the hardware description after
- * ieee80211_register_hw */
-int ieee80211_update_hw(struct ieee80211_hw *hw);
+/* Register a new hardware PHYMODE capability to the stack. */
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+			      struct ieee80211_hw_mode *mode);
 
 /* Unregister a hardware device. This function instructs 802.11 code to free
  * allocated resources and unregister netdevices from the kernel. */
Index: bu3sch-wireless-dev/net/d80211/ieee80211.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211.c	2006-12-05 
18:09:35.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211.c	2006-12-13 19:40:05.000000000 
+0100
@@ -1915,7 +1915,8 @@ int ieee80211_if_config_beacon(struct ne
 
 int ieee80211_hw_config(struct ieee80211_local *local)
 {
-	int i, ret = 0;
+	struct ieee80211_hw_mode *mode;
+	int ret = 0;
 
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 	printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
@@ -1926,12 +1927,10 @@ int ieee80211_hw_config(struct ieee80211
 	if (local->ops->config)
 		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
 
-	for (i = 0; i < local->hw.num_modes; i++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[i];
+	list_for_each_entry(mode, &local->modes_list, list) {
 		if (mode->mode == local->hw.conf.phymode) {
-			if (local->curr_rates != mode->rates) {
+			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);
@@ -2511,10 +2510,10 @@ ieee80211_rx_h_data(struct ieee80211_txr
 static struct ieee80211_rate *
 ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
 {
-	int m, r;
+	struct ieee80211_hw_mode *mode;
+	int r;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[m];
+	list_for_each_entry(mode, &local->modes_list, list) {
 		if (mode->mode != phymode)
 			continue;
 		for (r = 0; r < mode->num_rates; r++) {
@@ -4351,24 +4350,6 @@ void ieee80211_if_mgmt_setup(struct net_
 	dev->destructor = ieee80211_if_free;
 }
 
-static void ieee80211_precalc_modes(struct ieee80211_local *local)
-{
-	struct ieee80211_hw_modes *mode;
-	struct ieee80211_rate *rate;
-	struct ieee80211_hw *hw = &local->hw;
-	int m, r;
-
-	local->hw_modes = 0;
-	for (m = 0; m < hw->num_modes; m++) {
-		mode = &hw->modes[m];
-		local->hw_modes |= 1 << mode->mode;
-		for (r = 0; r < mode->num_rates; r++) {
-			rate = &mode->rates[r];
-			rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
-		}
-	}
-}
-
 int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
 				 const char *name)
 {
@@ -4461,6 +4442,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 	local->hw.priv = (char *)mdev->priv +
 			 ((sizeof(struct ieee80211_sub_if_data) +
 			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+	local->hw.queues = 1; /* default */
 
 	local->mdev = mdev;
 	local->rx_pre_handlers = ieee80211_rx_pre_handlers;
@@ -4482,6 +4464,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 
         init_timer(&local->scan.timer); /* clear it out */
 
+	INIT_LIST_HEAD(&local->modes_list);
+
 	spin_lock_init(&local->sub_if_lock);
 	INIT_LIST_HEAD(&local->sub_if_list);
 
@@ -4546,9 +4530,6 @@ int ieee80211_register_hw(struct ieee802
 
 	local->hw.conf.beacon_int = 1000;
 
-	/* Don't care about the result */
-	ieee80211_update_hw(local_to_hw(local));
-
 	result = sta_info_start(local);
 	if (result < 0)
 		goto fail_sta_info;
@@ -4633,35 +4614,38 @@ fail_sysfs:
 }
 EXPORT_SYMBOL(ieee80211_register_hw);
 
-int ieee80211_update_hw(struct ieee80211_hw *hw)
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+			      struct ieee80211_hw_mode *mode)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_rate *rate;
+	int i;
 
-	/* Backwards compatibility for low-level drivers that do not set number
-	 * of TX queues. */
-	if (hw->queues == 0)
-		hw->queues = 1;
-
-	if (!hw->modes || !hw->modes->channels || !hw->modes->rates ||
-	    !hw->modes->num_channels || !hw->modes->num_rates)
-		return -1;
+	INIT_LIST_HEAD(&mode->list);
+	list_add_tail(&mode->list, &local->modes_list);
 
-	ieee80211_precalc_modes(local);
-	local->hw.conf.phymode = hw->modes[0].mode;
-	local->curr_rates = hw->modes[0].rates;
-	local->num_curr_rates = hw->modes[0].num_rates;
-	ieee80211_prepare_rates(local);
-
-	local->hw.conf.freq = local->hw.modes[0].channels[0].freq;
-	local->hw.conf.channel = local->hw.modes[0].channels[0].chan;
-	local->hw.conf.channel_val = local->hw.modes[0].channels[0].val;
+	local->hw_modes |= (1 << mode->mode);
+	for (i = 0; i < mode->num_rates; i++) {
+		rate = &(mode->rates[i]);
+		rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
+	}
+
+	if (!local->curr_rates) {
+		/* Default to this mode */
+		local->hw.conf.phymode = mode->mode;
+		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);
-	/* FIXME: Invoke config to allow driver to set the channel. */
 
 	return 0;
 }
-EXPORT_SYMBOL(ieee80211_update_hw);
+EXPORT_SYMBOL(ieee80211_register_hwmode);
 
 void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 {
Index: bu3sch-wireless-dev/net/d80211/ieee80211_i.h
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211_i.h	2006-12-05 
18:09:35.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211_i.h	2006-12-13 19:40:05.000000000 
+0100
@@ -181,7 +181,7 @@ struct ieee80211_passive_scan {
 	int channel; /* channel to be scanned */
         int tries;
 
-        int mode_idx;
+	struct ieee80211_hw_mode *mode;
         int chan_idx;
 
 	int freq;
@@ -336,6 +336,9 @@ struct ieee80211_local {
 
 	struct ieee80211_ops *ops;
 
+	/* List of registered struct ieee80211_hw_mode */
+	struct list_head modes_list;
+
 	struct net_device *mdev; /* wmaster# - "master" 802.11 device */
 	struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
 	int open_count;
@@ -425,7 +428,7 @@ struct ieee80211_local {
         spinlock_t sub_if_lock; /* mutex for STA data structures */
         struct list_head sub_if_list;
 	int sta_scanning;
-	int scan_hw_mode_idx;
+	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;
Index: bu3sch-wireless-dev/net/d80211/ieee80211_ioctl.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211_ioctl.c	2006-12-05 
18:09:35.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211_ioctl.c	2006-12-13 
19:40:05.000000000 +0100
@@ -120,43 +120,45 @@ static int ieee80211_ioctl_get_hw_featur
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 	u8 *pos = param->u.hw_features.data;
 	int left = param_len - (pos - (u8 *) param);
-	int mode, i;
+	int i;
 	struct hostapd_ioctl_hw_modes_hdr *hdr;
 	struct ieee80211_rate_data *rate;
 	struct ieee80211_channel_data *chan;
+	struct ieee80211_hw_mode *mode;
 
 	param->u.hw_features.flags = 0;
 	if (local->hw.flags & IEEE80211_HW_DATA_NULLFUNC_ACK)
 		param->u.hw_features.flags |= HOSTAP_HW_FLAG_NULLFUNC_OK;
 
-	param->u.hw_features.num_modes = local->hw.num_modes;
-	for (mode = 0; mode < local->hw.num_modes; mode++) {
+	param->u.hw_features.num_modes = 0;
+	list_for_each_entry(mode, &local->modes_list, list) {
 		int clen, rlen;
-		struct ieee80211_hw_modes *m = &local->hw.modes[mode];
-		clen = m->num_channels * sizeof(struct ieee80211_channel_data);
-		rlen = m->num_rates * sizeof(struct ieee80211_rate_data);
+
+		param->u.hw_features.num_modes++;
+		clen = mode->num_channels * sizeof(struct ieee80211_channel_data);
+		rlen = mode->num_rates * sizeof(struct ieee80211_rate_data);
 		if (left < sizeof(*hdr) + clen + rlen)
 			return -E2BIG;
 		left -= sizeof(*hdr) + clen + rlen;
 
 		hdr = (struct hostapd_ioctl_hw_modes_hdr *) pos;
-		hdr->mode = m->mode;
-		hdr->num_channels = m->num_channels;
-		hdr->num_rates = m->num_rates;
+		hdr->mode = mode->mode;
+		hdr->num_channels = mode->num_channels;
+		hdr->num_rates = mode->num_rates;
 
 		pos = (u8 *) (hdr + 1);
 		chan = (struct ieee80211_channel_data *) pos;
-		for (i = 0; i < m->num_channels; i++) {
-			chan[i].chan = m->channels[i].chan;
-			chan[i].freq = m->channels[i].freq;
-			chan[i].flag = m->channels[i].flag;
+		for (i = 0; i < mode->num_channels; i++) {
+			chan[i].chan = mode->channels[i].chan;
+			chan[i].freq = mode->channels[i].freq;
+			chan[i].flag = mode->channels[i].flag;
 		}
 		pos += clen;
 
 		rate = (struct ieee80211_rate_data *) pos;
-		for (i = 0; i < m->num_rates; i++) {
-			rate[i].rate = m->rates[i].rate;
-			rate[i].flags = m->rates[i].flags;
+		for (i = 0; i < mode->num_rates; i++) {
+			rate[i].rate = mode->rates[i].rate;
+			rate[i].flags = mode->rates[i].flags;
 		}
 		pos += rlen;
 	}
@@ -198,8 +200,7 @@ static int ieee80211_ioctl_scan(struct n
 		param->u.scan.last_rx = local->scan.rx_packets;
 		local->scan.rx_packets = -1;
 	}
-	param->u.scan.channel = local->hw.modes[local->scan.mode_idx].
-		channels[local->scan.chan_idx].chan;
+	param->u.scan.channel = 
local->scan.mode->channels[local->scan.chan_idx].chan;
 
 	return 0;
 }
@@ -1357,19 +1358,16 @@ static int ieee80211_ioctl_set_channel_f
 					    struct prism2_hostapd_param *param)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
-	struct ieee80211_hw_modes *mode = NULL;
+	struct ieee80211_hw_mode *mode;
 	struct ieee80211_channel *chan = NULL;
 	int i;
 
-	for (i = 0; i < local->hw.num_modes; i++) {
-		mode = &local->hw.modes[i];
+	list_for_each_entry(mode, &local->modes_list, list) {
 		if (mode->mode == param->u.set_channel_flag.mode)
-			break;
-		mode = NULL;
+			goto found;
 	}
-
-	if (!mode)
-		return -ENOENT;
+	return -ENOENT;
+found:
 
 	for (i = 0; i < mode->num_channels; i++) {
 		chan = &mode->channels[i];
@@ -1706,10 +1704,10 @@ static void ieee80211_unmask_channel(str
 static int ieee80211_unmask_channels(struct net_device *dev)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
-	int m, c;
+	struct ieee80211_hw_mode *mode;
+	int c;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[m];
+	list_for_each_entry(mode, &local->modes_list, list) {
 		for (c = 0; c < mode->num_channels; c++) {
 			ieee80211_unmask_channel(dev, mode->mode,
 						 &mode->channels[c]);
@@ -1807,7 +1805,8 @@ int ieee80211_ioctl_siwfreq(struct net_d
 			    struct iw_freq *freq, char *extra)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
-	int m, c, nfreq, set = 0;
+	struct ieee80211_hw_mode *mode;
+	int c, nfreq, set = 0;
 
 	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
 	if (freq->e == 0)
@@ -1822,8 +1821,7 @@ int ieee80211_ioctl_siwfreq(struct net_d
 			return -EINVAL;
 	}
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[m];
+	list_for_each_entry(mode, &local->modes_list, list) {
 		for (c = 0; c < mode->num_channels; c++) {
 			struct ieee80211_channel *chan = &mode->channels[c];
 			if (chan->flag & IEEE80211_CHAN_W_SCAN &&
@@ -2166,10 +2164,10 @@ static int ieee80211_ioctl_giwretry(stru
 
 static void ieee80211_ioctl_unmask_channels(struct ieee80211_local *local)
 {
-	int m, c;
+	struct ieee80211_hw_mode *mode;
+	int c;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[m];
+	list_for_each_entry(mode, &local->modes_list, list) {
 		for (c = 0; c < mode->num_channels; c++) {
 			struct ieee80211_channel *chan = &mode->channels[c];
 			chan->flag |= IEEE80211_CHAN_W_SCAN;
Index: bu3sch-wireless-dev/net/d80211/ieee80211_scan.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211_scan.c	2006-12-05 
18:09:35.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211_scan.c	2006-12-13 
19:40:05.000000000 +0100
@@ -24,49 +24,49 @@
 #define SCAN_TXRX_THRESHOLD 75
 
 static void get_channel_params(struct ieee80211_local *local, int channel,
-				struct ieee80211_hw_modes **mode,
+				struct ieee80211_hw_mode **mode,
 				struct ieee80211_channel **chan)
 {
-	int m;
+	struct ieee80211_hw_mode *m;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		*mode = &local->hw.modes[m];
-		if ((*mode)->mode == local->hw.conf.phymode)
+	list_for_each_entry(m, &local->modes_list, list) {
+		*mode = m;
+		if (m->mode == local->hw.conf.phymode)
 			break;
 	}
-	local->scan.mode_idx = m;
+	local->scan.mode = m;
 	local->scan.chan_idx = 0;
 	do {
-		*chan = &(*mode)->channels[local->scan.chan_idx];
-		if ((*chan)->chan == channel) {
+		*chan = &m->channels[local->scan.chan_idx];
+		if ((*chan)->chan == channel)
 			return;
-		}
 		local->scan.chan_idx++;
-	} while (local->scan.chan_idx < (*mode)->num_channels);
+	} while (local->scan.chan_idx < m->num_channels);
 	*chan = NULL;
 }
 
 
 static void next_chan_same_mode(struct ieee80211_local *local,
-				struct ieee80211_hw_modes **mode,
+				struct ieee80211_hw_mode **mode,
 				struct ieee80211_channel **chan)
 {
-	int m, prev;
+	struct ieee80211_hw_mode *m;
+	int prev;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		*mode = &local->hw.modes[m];
-		if ((*mode)->mode == local->hw.conf.phymode)
+	list_for_each_entry(m, &local->modes_list, list) {
+		*mode = m;
+		if (m->mode == local->hw.conf.phymode)
 			break;
 	}
-	local->scan.mode_idx = m;
+	local->scan.mode = m;
 
 	/* Select next channel - scan only channels marked with W_SCAN flag */
 	prev = local->scan.chan_idx;
 	do {
 		local->scan.chan_idx++;
-		if (local->scan.chan_idx >= (*mode)->num_channels)
+		if (local->scan.chan_idx >= m->num_channels)
 			local->scan.chan_idx = 0;
-		*chan = &(*mode)->channels[local->scan.chan_idx];
+		*chan = &m->channels[local->scan.chan_idx];
 		if ((*chan)->flag & IEEE80211_CHAN_W_SCAN)
 			break;
 	} while (local->scan.chan_idx != prev);
@@ -74,43 +74,44 @@ static void next_chan_same_mode(struct i
 
 
 static void next_chan_all_modes(struct ieee80211_local *local,
-				struct ieee80211_hw_modes **mode,
+				struct ieee80211_hw_mode **mode,
 				struct ieee80211_channel **chan)
 {
-	int prev, prev_m;
-
-	if (local->scan.mode_idx >= local->hw.num_modes) {
-		local->scan.mode_idx = 0;
-		local->scan.chan_idx = 0;
-	}
+	struct ieee80211_hw_mode *prev_m;
+	int prev;
 
 	/* Select next channel - scan only channels marked with W_SCAN flag */
 	prev = local->scan.chan_idx;
-	prev_m = local->scan.mode_idx;
+	prev_m = local->scan.mode;
 	do {
-		*mode = &local->hw.modes[local->scan.mode_idx];
+		*mode = local->scan.mode;
 		local->scan.chan_idx++;
 		if (local->scan.chan_idx >= (*mode)->num_channels) {
+			struct list_head *next;
+
 			local->scan.chan_idx = 0;
-			local->scan.mode_idx++;
-			if (local->scan.mode_idx >= local->hw.num_modes)
-				local->scan.mode_idx = 0;
-			*mode = &local->hw.modes[local->scan.mode_idx];
+			next = (*mode)->list.next;
+			if (next == &local->modes_list)
+				next = next->next;
+			*mode = list_entry(next,
+					   struct ieee80211_hw_mode,
+					   list);
+			local->scan.mode = *mode;
 		}
 		*chan = &(*mode)->channels[local->scan.chan_idx];
 		if ((*chan)->flag & IEEE80211_CHAN_W_SCAN)
 			break;
 	} while (local->scan.chan_idx != prev ||
-		 local->scan.mode_idx != prev_m);
+		 local->scan.mode != prev_m);
 }
 
 
 static void ieee80211_scan_start(struct ieee80211_local *local,
 				 struct ieee80211_scan_conf *conf)
 {
-	int old_mode_idx = local->scan.mode_idx;
+	struct ieee80211_hw_mode *old_mode = local->scan.mode;
 	int old_chan_idx = local->scan.chan_idx;
-	struct ieee80211_hw_modes *mode = NULL;
+	struct ieee80211_hw_mode *mode = NULL;
 	struct ieee80211_channel *chan = NULL;
 	int ret;
 
@@ -189,7 +190,7 @@ static void ieee80211_scan_start(struct 
 		if (ret == -EAGAIN) {
 			local->scan.timer.expires = jiffies +
 				(local->scan.interval * HZ / 100);
-			local->scan.mode_idx = old_mode_idx;
+			local->scan.mode = old_mode;
 			local->scan.chan_idx = old_chan_idx;
 		} else {
 			printk(KERN_DEBUG "%s: Got unknown error from "
@@ -207,23 +208,17 @@ static void ieee80211_scan_start(struct 
 static void ieee80211_scan_stop(struct ieee80211_local *local,
 				struct ieee80211_scan_conf *conf)
 {
-	struct ieee80211_hw_modes *mode;
+	struct ieee80211_hw_mode *mode;
 	struct ieee80211_channel *chan;
 	int wait;
 
 	if (!local->ops->passive_scan)
 		return;
 
-	if (local->scan.mode_idx >= local->hw.num_modes) {
-		local->scan.mode_idx = 0;
-		local->scan.chan_idx = 0;
-	}
+	mode = local->scan.mode;
 
-	mode = &local->hw.modes[local->scan.mode_idx];
-
-	if (local->scan.chan_idx >= mode->num_channels) {
+	if (local->scan.chan_idx >= mode->num_channels)
 		local->scan.chan_idx = 0;
-	}
 
 	chan = &mode->channels[local->scan.chan_idx];
 
Index: bu3sch-wireless-dev/net/d80211/ieee80211_sta.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211_sta.c	2006-12-05 
18:09:35.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211_sta.c	2006-12-13 
19:40:05.000000000 +0100
@@ -1380,6 +1380,7 @@ static void ieee80211_rx_bss_info(struct
 	if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
 	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
 	    (sta = sta_info_get(local, mgmt->sa))) {
+	    	struct ieee80211_hw_mode *mode;
 		struct ieee80211_rate *rates;
 		size_t num_rates;
 		u32 supp_rates, prev_rates;
@@ -1389,8 +1390,7 @@ static void ieee80211_rx_bss_info(struct
 		num_rates = local->num_curr_rates;
 		oper_mode = local->sta_scanning ? local->scan_oper_phymode :
 			local->hw.conf.phymode;
-		for (i = 0; i < local->hw.num_modes; i++) {
-			struct ieee80211_hw_modes *mode = &local->hw.modes[i];
+		list_for_each_entry(mode, &local->modes_list, list) {
 			if (oper_mode == mode->mode) {
 				rates = mode->rates;
 				num_rates = mode->num_rates;
@@ -1924,10 +1924,10 @@ static void ieee80211_sta_new_auth(struc
 
 static int ieee80211_ibss_allowed(struct ieee80211_local *local)
 {
-	int m, c;
+	struct ieee80211_hw_mode *mode;
+	int c;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[m];
+	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++) {
@@ -2383,10 +2383,10 @@ static int ieee80211_sta_restore_oper_ch
 
 static int ieee80211_active_scan(struct ieee80211_local *local)
 {
-	int m, c;
+	struct ieee80211_hw_mode *mode;
+	int c;
 
-	for (m = 0; m < local->hw.num_modes; m++) {
-		struct ieee80211_hw_modes *mode = &local->hw.modes[m];
+	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++) {
@@ -2433,7 +2433,7 @@ static void ieee80211_sta_scan_work(void
 	struct net_device *dev = ptr;
 	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_hw_modes *mode;
+	struct ieee80211_hw_mode *mode;
 	struct ieee80211_channel *chan;
 	int skip;
 	unsigned long next_delay = 0;
@@ -2443,10 +2443,9 @@ static void ieee80211_sta_scan_work(void
 
 	switch (local->scan_state) {
 	case SCAN_SET_CHANNEL:
-		mode = &local->hw.modes[local->scan_hw_mode_idx];
-		if (local->scan_hw_mode_idx >= local->hw.num_modes ||
-		    (local->scan_hw_mode_idx + 1 == local->hw.num_modes &&
-		     local->scan_channel_idx >= mode->num_channels)) {
+		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",
@@ -2486,10 +2485,13 @@ static void ieee80211_sta_scan_work(void
 		}
 
 		local->scan_channel_idx++;
-		if (local->scan_channel_idx >=
-		    local->hw.modes[local->scan_hw_mode_idx].num_channels) {
-			local->scan_hw_mode_idx++;
-			local->scan_channel_idx = 0;
+		if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
+			if (local->scan_hw_mode->list.next != &local->modes_list) {
+				local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
+								 struct ieee80211_hw_mode,
+								 list);
+				local->scan_channel_idx = 0;
+			}
 		}
 
 		if (skip)
@@ -2575,7 +2577,9 @@ int ieee80211_sta_req_scan(struct net_de
 	} else
 		local->scan_ssid_len = 0;
 	local->scan_state = SCAN_SET_CHANNEL;
-	local->scan_hw_mode_idx = 0;
+	local->scan_hw_mode = list_entry(local->modes_list.next,
+					 struct ieee80211_hw_mode,
+					 list);
 	local->scan_channel_idx = 0;
 	INIT_WORK(&local->scan_work, ieee80211_sta_scan_work, dev);
 	schedule_work(&local->scan_work);
Index: bu3sch-wireless-dev/net/d80211/ieee80211_sysfs.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211_sysfs.c	2006-12-05 
18:09:35.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211_sysfs.c	2006-12-13 
19:40:05.000000000 +0100
@@ -189,15 +189,13 @@ __IEEE80211_LOCAL_SHOW(tx_power_reductio
 static ssize_t ieee80211_local_fmt_modes(struct ieee80211_local *local,
 					 char *buf)
 {
-	int i;
-	struct ieee80211_hw_modes *mode;
+	struct ieee80211_hw_mode *mode;
 	char *p = buf;
 
-	/* FIXME: locking against ieee80211_update_hw? */
-	for (i = 0; i < local->hw.num_modes; i++) {
-		mode = &local->hw.modes[i];
+	/* FIXME: Locking? Could register a mode in the meantime. */
+	list_for_each_entry(mode, &local->modes_list, list)
 		p += sprintf(p, "%s\n", ieee80211_mode_str_short(mode->mode));
-	}
+
 	return (p - buf);
 }
 __IEEE80211_LOCAL_SHOW(modes);

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
  2006-12-14 18:20 [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list Michael Buesch
@ 2006-12-15 13:48 ` Jiri Benc
  2006-12-15 13:54   ` Michael Buesch
  2006-12-16  6:40 ` Michael Wu
  1 sibling, 1 reply; 8+ messages in thread
From: Jiri Benc @ 2006-12-15 13:48 UTC (permalink / raw)
  To: Michael Buesch; +Cc: linville, netdev, bcm43xx-dev

On Thu, 14 Dec 2006 19:20:11 +0100, Michael Buesch wrote:
> This turns the PHY-modes list into a linked list.
> The advantage is that drivers can add modes dynamically, as they probe
> them and don't have to settle to a given arraysize at the beginning
> of probing.

ACK.

> @@ -198,8 +200,7 @@ static int ieee80211_ioctl_scan(struct n
>  		param->u.scan.last_rx = local->scan.rx_packets;
>  		local->scan.rx_packets = -1;
>  	}
> -	param->u.scan.channel = local->hw.modes[local->scan.mode_idx].
> -		channels[local->scan.chan_idx].chan;
> +	param->u.scan.channel = 
> local->scan.mode->channels[local->scan.chan_idx].chan;
>  
>  	return 0;
>  }

The patch is malformed. Fixed and applied to my tree.

Thanks,

 Jiri

-- 
Jiri Benc
SUSE Labs

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
  2006-12-15 13:48 ` Jiri Benc
@ 2006-12-15 13:54   ` Michael Buesch
       [not found]     ` <200612151454.55508.mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Michael Buesch @ 2006-12-15 13:54 UTC (permalink / raw)
  To: Jiri Benc; +Cc: bcm43xx-dev, linville, netdev

On Friday 15 December 2006 14:48, Jiri Benc wrote:
> On Thu, 14 Dec 2006 19:20:11 +0100, Michael Buesch wrote:
> > This turns the PHY-modes list into a linked list.
> > The advantage is that drivers can add modes dynamically, as they probe
> > them and don't have to settle to a given arraysize at the beginning
> > of probing.
> 
> ACK.

Thanks. Will submit fixes for the other drivers, too.

> > @@ -198,8 +200,7 @@ static int ieee80211_ioctl_scan(struct n
> >  		param->u.scan.last_rx = local->scan.rx_packets;
> >  		local->scan.rx_packets = -1;
> >  	}
> > -	param->u.scan.channel = local->hw.modes[local->scan.mode_idx].
> > -		channels[local->scan.chan_idx].chan;
> > +	param->u.scan.channel = 
> > local->scan.mode->channels[local->scan.chan_idx].chan;
> >  
> >  	return 0;
> >  }
> 
> The patch is malformed. Fixed and applied to my tree.

I'm sorry. Forgot to remove the "wrap at ~80chars option in my mailer.

Can you also apply the bcm43xx fix for this to your tree?
I think that should be easiest and prevent long-living breakage.

-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
       [not found]     ` <200612151454.55508.mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
@ 2006-12-15 14:06       ` Jiri Benc
       [not found]         ` <20061215150655.50a728c4-IhiK2ZEFs2oCVLCxKZUutA@public.gmane.org>
  2006-12-15 15:37         ` Michael Buesch
  0 siblings, 2 replies; 8+ messages in thread
From: Jiri Benc @ 2006-12-15 14:06 UTC (permalink / raw)
  To: Michael Buesch
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w,
	linville-2XuSBdqkA4R54TAoqtyWWQ

On Fri, 15 Dec 2006 14:54:55 +0100, Michael Buesch wrote:
> Can you also apply the bcm43xx fix for this to your tree?
> I think that should be easiest and prevent long-living breakage.

It doesn't apply :-( It's probably easy to fix but I'd rather leave it
to you to not make any damage.

Thanks,

 Jiri

-- 
Jiri Benc
SUSE Labs

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
       [not found]         ` <20061215150655.50a728c4-IhiK2ZEFs2oCVLCxKZUutA@public.gmane.org>
@ 2006-12-15 14:33           ` Michael Buesch
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Buesch @ 2006-12-15 14:33 UTC (permalink / raw)
  To: Jiri Benc
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w,
	linville-2XuSBdqkA4R54TAoqtyWWQ

On Friday 15 December 2006 15:06, Jiri Benc wrote:
> On Fri, 15 Dec 2006 14:54:55 +0100, Michael Buesch wrote:
> > Can you also apply the bcm43xx fix for this to your tree?
> > I think that should be easiest and prevent long-living breakage.
> 
> It doesn't apply :-( It's probably easy to fix but I'd rather leave it
> to you to not make any damage.

Uh, yeah. Possible. It's diffed against my tree. Forgot that
I have some other changes in there.
I will resend a fixed fix :)

-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
  2006-12-15 14:06       ` Jiri Benc
       [not found]         ` <20061215150655.50a728c4-IhiK2ZEFs2oCVLCxKZUutA@public.gmane.org>
@ 2006-12-15 15:37         ` Michael Buesch
  1 sibling, 0 replies; 8+ messages in thread
From: Michael Buesch @ 2006-12-15 15:37 UTC (permalink / raw)
  To: Jiri Benc; +Cc: bcm43xx-dev, linville, netdev

On Friday 15 December 2006 15:06, Jiri Benc wrote:
> On Fri, 15 Dec 2006 14:54:55 +0100, Michael Buesch wrote:
> > Can you also apply the bcm43xx fix for this to your tree?
> > I think that should be easiest and prevent long-living breakage.
> 
> It doesn't apply :-( It's probably easy to fix but I'd rather leave it
> to you to not make any damage.

Here's the fixed patch diffed against your tree.

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

Index: jbenc-dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- jbenc-dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-12-15 15:58:04.000000000 +0100
+++ jbenc-dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-12-15 16:17:30.000000000 +0100
@@ -503,6 +503,8 @@ struct bcm43xx_phyinfo {
 	enum bcm43xx_firmware_compat fw;
 	/* The TX header length. This depends on the firmware. */
 	size_t txhdr_size;
+
+	struct ieee80211_hw_mode hwmode;
 };
 
 
Index: jbenc-dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- jbenc-dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-12-15 15:58:04.000000000 +0100
+++ jbenc-dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-12-15 16:30:55.000000000 +0100
@@ -2845,19 +2845,25 @@ static void bcm43xx_chipset_detach(struc
 
 static void bcm43xx_free_modes(struct bcm43xx_private *bcm)
 {
-	struct ieee80211_hw *hw = bcm->ieee;
+	struct ssb_core *core;
+	struct bcm43xx_corepriv_80211 *wlpriv;
+	struct bcm43xx_phyinfo *phy;
 	int i;
 
-	for (i = 0; i < hw->num_modes; i++) {
-		kfree(hw->modes[i].channels);
-		kfree(hw->modes[i].rates);
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		core = bcm->wlcores[i];
+		wlpriv = core->priv;
+		phy = &wlpriv->phy;
+
+		kfree(phy->hwmode.channels);
+		phy->hwmode.channels = NULL;
+		kfree(phy->hwmode.rates);
+		phy->hwmode.rates = NULL;
 	}
-	kfree(hw->modes);
-	hw->modes = NULL;
-	hw->num_modes = 0;
 }
 
-static int bcm43xx_append_mode(struct ieee80211_hw *hw,
+static int bcm43xx_append_mode(struct bcm43xx_private *bcm,
+			       struct bcm43xx_phyinfo *phy,
 			       int mode_id,
 			       int nr_channels,
 			       const struct ieee80211_channel *channels,
@@ -2866,10 +2872,10 @@ static int bcm43xx_append_mode(struct ie
 			       int nr_rates2,
 			       const struct ieee80211_rate *rates2)
 {
-	struct ieee80211_hw_modes *mode;
+	struct ieee80211_hw_mode *mode;
 	int err = -ENOMEM;
 
-	mode = &(hw->modes[hw->num_modes]);
+	mode = &phy->hwmode;
 
 	mode->mode = mode_id;
 	mode->num_channels = nr_channels;
@@ -2890,11 +2896,14 @@ static int bcm43xx_append_mode(struct ie
 		       sizeof(*rates2) * nr_rates2);
 	}
 
-	hw->num_modes++;
-	err = 0;
+	err = ieee80211_register_hwmode(bcm->ieee, mode);
+	if (err)
+		goto err_free_rates;
 out:
 	return err;
 
+err_free_rates:
+	kfree(mode->rates);
 err_free_channels:
 	kfree(mode->channels);
 	goto out;
@@ -2903,17 +2912,9 @@ err_free_channels:
 static int bcm43xx_setup_modes(struct bcm43xx_private *bcm)
 {
 	int err = -ENOMEM;
-	struct ieee80211_hw *hw = bcm->ieee;
 	struct ssb_core *core;
 	struct bcm43xx_corepriv_80211 *wlpriv;
-	int i, nr_modes;
-
-	nr_modes = bcm->nr_80211_available;
-	hw->modes = kzalloc(sizeof(*(hw->modes)) * nr_modes,
-			      GFP_KERNEL);
-	if (!hw->modes)
-		goto out;
-	hw->num_modes = 0;
+	int i;
 
 	for (i = 0; i < bcm->nr_80211_available; i++) {
 		core = bcm->wlcores[i];
@@ -2921,7 +2922,7 @@ static int bcm43xx_setup_modes(struct bc
 
 		switch (wlpriv->phy.type) {
 		case BCM43xx_PHYTYPE_A:
-			err = bcm43xx_append_mode(bcm->ieee, MODE_IEEE80211A,
+			err = bcm43xx_append_mode(bcm, &wlpriv->phy, MODE_IEEE80211A,
 						  ARRAY_SIZE(bcm43xx_a_chantable),
 						  bcm43xx_a_chantable,
 						  ARRAY_SIZE(bcm43xx_ofdm_ratetable),
@@ -2929,7 +2930,7 @@ static int bcm43xx_setup_modes(struct bc
 						  0, NULL);
 			break;
 		case BCM43xx_PHYTYPE_B:
-			err = bcm43xx_append_mode(bcm->ieee, MODE_IEEE80211B,
+			err = bcm43xx_append_mode(bcm, &wlpriv->phy, MODE_IEEE80211B,
 						  ARRAY_SIZE(bcm43xx_bg_chantable),
 						  bcm43xx_bg_chantable,
 						  ARRAY_SIZE(bcm43xx_cck_ratetable),
@@ -2937,7 +2938,7 @@ static int bcm43xx_setup_modes(struct bc
 						  0, NULL);
 			break;
 		case BCM43xx_PHYTYPE_G:
-			err = bcm43xx_append_mode(bcm->ieee, MODE_IEEE80211G,
+			err = bcm43xx_append_mode(bcm, &wlpriv->phy, MODE_IEEE80211G,
 						  ARRAY_SIZE(bcm43xx_bg_chantable),
 						  bcm43xx_bg_chantable,
 						  ARRAY_SIZE(bcm43xx_ofdm_ratetable),
@@ -3180,7 +3181,6 @@ bcm->wlcore = active_core;
 	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->ieee->perm_addr));
 	bcm43xx_security_init(bcm);
 	bcm43xx_measure_channel_change_time(bcm);
-	ieee80211_update_hw(bcm->ieee);
 	ieee80211_start_queues(bcm->ieee);
 
 	/* Let's go! Be careful after enabling the IRQs.


-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list
  2006-12-14 18:20 [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list Michael Buesch
  2006-12-15 13:48 ` Jiri Benc
@ 2006-12-16  6:40 ` Michael Wu
  2000-01-01  0:23   ` Michael Buesch
  1 sibling, 1 reply; 8+ messages in thread
From: Michael Wu @ 2006-12-16  6:40 UTC (permalink / raw)
  To: Michael Buesch; +Cc: jbenc, linville, netdev, bcm43xx-dev

[-- Attachment #1: Type: text/plain, Size: 363 bytes --]

On Thursday 14 December 2006 13:20, Michael Buesch wrote:
> -int ieee80211_update_hw(struct ieee80211_hw *hw)
> +int ieee80211_register_hwmode(struct ieee80211_hw *hw,
> +			      struct ieee80211_hw_mode *mode)
Looks like this function never returns nonzero now. Can it return void 
instead? This would simplify the fixes for drivers a bit.

-Michael Wu

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2006-12-16 15:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-14 18:20 [PATCH 1/2] d80211: Turn PHYmode list from an array into a linked list Michael Buesch
2006-12-15 13:48 ` Jiri Benc
2006-12-15 13:54   ` Michael Buesch
     [not found]     ` <200612151454.55508.mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
2006-12-15 14:06       ` Jiri Benc
     [not found]         ` <20061215150655.50a728c4-IhiK2ZEFs2oCVLCxKZUutA@public.gmane.org>
2006-12-15 14:33           ` Michael Buesch
2006-12-15 15:37         ` Michael Buesch
2006-12-16  6:40 ` Michael Wu
2000-01-01  0:23   ` Michael Buesch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).