All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/17] d80211 patches
@ 2006-04-21 20:11 Jiri Benc
  2006-04-21 20:11 ` [PATCH 1/17] d80211: Replace MODULE_PARM with module_param Jiri Benc
                   ` (17 more replies)
  0 siblings, 18 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Hi John,

please pull to your wireless-dev tree from

git://git.kernel.org/pub/scm/linux/kernel/git/jbenc/dscape.git up

to obtain following patches. They were all posted to netdev previously and
are all discussed with Jouni (except 7th patch, but that is quite simple and
shouldn't cause any harm).

Also, the new rule of required kerneldoc documentation is hopefully
fulfilled - the only exception is ieee80211_hw structure, which is
well-commented but with comments inside. I think it will be best to convert
comments in ieee80211_hw by a separate patch.

Please note that these changes break d80211 drivers.

Jiri Benc:
      d80211: symlinks to wiphy in sysfs
      d80211: allow WDS remote to by set by WE
      d80211: add IBSS and monitor interface types
      d80211: non-shared interface types
      d80211: remove local->bssid variable
      d80211: rename IEEE80211_SUB_IF_TYPE_ constants
      d80211: ask driver for allowed iface combinations
      d80211: remove obsolete stuff
      d80211: fix interface configuration
      d80211: rename adm_status to radio_enabled
      d80211: interface types changeable by SIOCSIWMODE
      d80211: master interface auto up/down
      d80211: set_multicast_list
      d80211: fix handling of received frames
      d80211: fix monitor interfaces
      d80211: fix AP interfaces

Jouni Malinen:
      d80211: Replace MODULE_PARM with module_param

 include/net/d80211.h         |  179 ++++-
 net/d80211/Makefile          |    1 
 net/d80211/hostapd_ioctl.h   |    3 
 net/d80211/ieee80211.c       | 1473 +++++++++++++++----------------------------
 net/d80211/ieee80211_dev.c   |   16 
 net/d80211/ieee80211_i.h     |   80 +-
 net/d80211/ieee80211_iface.c |  299 ++++++++
 net/d80211/ieee80211_ioctl.c |  468 ++++++-------
 net/d80211/ieee80211_proc.c  |   34 
 net/d80211/ieee80211_sta.c   |  109 +--
 net/d80211/ieee80211_sysfs.c |   95 +-
 net/d80211/wme.c             |    3 
 12 files changed, 1376 insertions(+), 1384 deletions(-)

Jiri Benc
SUSE Labs

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

* [PATCH 1/17] d80211: Replace MODULE_PARM with module_param
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 2/17] d80211: symlinks to wiphy in sysfs Jiri Benc
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

From: Jouni Malinen <jkmaline@cc.hut.fi>

MODULE_PARM macro was removed and this broke net/d80211 build. Fix
this by using module_param instead of MODULE_PARM.

Signed-off-by: Jouni Malinen <jkmaline@cc.hut.fi>
Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211_ioctl.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

d0d54060410447c5eb354886ac0ae9cff73a4b2c
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 42a7abe..987f761 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -30,7 +30,7 @@ #include "aes_ccm.h"
 
 
 static int ieee80211_regdom = 0x10; /* FCC */
-MODULE_PARM(ieee80211_regdom, "i");
+module_param(ieee80211_regdom, int, 0444);
 MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK");
 
 /*
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(ieee80211_regdom, "IEEE
  * module.
  */
 static int ieee80211_japan_5ghz /* = 0 */;
-MODULE_PARM(ieee80211_japan_5ghz, "i");
+module_param(ieee80211_japan_5ghz, int, 0444);
 MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz");
 
 
-- 
1.3.0


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

* [PATCH 2/17] d80211: symlinks to wiphy in sysfs
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
  2006-04-21 20:11 ` [PATCH 1/17] d80211: Replace MODULE_PARM with module_param Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 3/17] d80211: allow WDS remote to by set by WE Jiri Benc
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

This patch adds symlinks under /sys/net/*/wiphy pointing to
/sys/class/ieee80211/phyX.

This allows new interfaces to be added by writing a new name to e.g.
/sys/net/wlan0/wiphy/add_iface.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211_dev.c   |   16 +++++++++++++
 net/d80211/ieee80211_i.h     |    1 +
 net/d80211/ieee80211_sysfs.c |   51 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 67 insertions(+), 1 deletions(-)

8ac63bdfba39115673abc492d7eb867c364b0fc4
diff --git a/net/d80211/ieee80211_dev.c b/net/d80211/ieee80211_dev.c
index 4302506..6278cfa 100644
--- a/net/d80211/ieee80211_dev.c
+++ b/net/d80211/ieee80211_dev.c
@@ -83,3 +83,19 @@ struct ieee80211_local *ieee80211_dev_fi
 	spin_unlock(&dev_list_lock);
 	return dev_item ? dev_item->local : NULL;
 }
+
+int ieee80211_dev_find_index(struct ieee80211_local *local)
+{
+	struct ieee80211_dev_list *dev_item;
+	int index = -1;
+
+	spin_lock(&dev_list_lock);
+	list_for_each_entry(dev_item, &dev_list, list) {
+		if (dev_item->local == local) {
+			index = dev_item->dev_index;
+			break;
+		}
+	}
+	spin_unlock(&dev_list_lock);
+	return index;
+}
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 0c1eeac..c217104 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -587,6 +587,7 @@ int ieee80211_sta_disassociate(struct ne
 int ieee80211_dev_alloc_index(struct ieee80211_local *local);
 void ieee80211_dev_free_index(struct ieee80211_local *local);
 struct ieee80211_local *ieee80211_dev_find(int index);
+int ieee80211_dev_find_index(struct ieee80211_local *local);
 
 /* ieee80211_sysfs.c */
 int ieee80211_register_sysfs(struct ieee80211_local *local);
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 6e7d3ea..32fb380 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -10,6 +10,7 @@ #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/if.h>
 #include <linux/interrupt.h>
+#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <net/d80211.h>
 #include "ieee80211_i.h"
@@ -124,12 +125,60 @@ void ieee80211_unregister_sysfs(struct i
 	class_device_del(&local->class_dev);
 }
 
+static int ieee80211_add_netdevice(struct class_device *cd,
+				   struct class_interface *cintf)
+{
+	struct net_device *dev = container_of(cd, struct net_device, class_dev);
+	struct ieee80211_local *local = dev->priv;
+
+	if (ieee80211_dev_find_index(local) < 0)
+		return 0;
+	return sysfs_create_link(&cd->kobj, &local->class_dev.kobj, "wiphy");
+}
+
+static void ieee80211_remove_netdevice(struct class_device *cd,
+				       struct class_interface *cintf)
+{
+	struct net_device *dev = container_of(cd, struct net_device, class_dev);
+	struct ieee80211_local *local = dev->priv;
+
+	if (ieee80211_dev_find_index(local) >= 0)
+		sysfs_remove_link(&cd->kobj, "wiphy");
+}
+
+static struct class_interface ieee80211_wiphy_cintf = {
+	.add = ieee80211_add_netdevice,
+	.remove = ieee80211_remove_netdevice,
+};
+
+/* Adds class interface watching for new network devices and adding "wiphy"
+ * attribute (symlink) to them. */
+static int ieee80211_register_wiphy_cintf(void)
+{
+	ieee80211_wiphy_cintf.class = loopback_dev.class_dev.class;
+	return class_interface_register(&ieee80211_wiphy_cintf);
+}
+
+static void ieee80211_unregister_wiphy_cintf(void)
+{
+	class_interface_unregister(&ieee80211_wiphy_cintf);
+}
+
 int ieee80211_sysfs_init(void)
 {
-	return class_register(&ieee80211_class);
+	int result;
+
+	result = class_register(&ieee80211_class);
+	if (result)
+		return result;
+	result = ieee80211_register_wiphy_cintf();
+	if (result)
+		class_unregister(&ieee80211_class);
+	return result;
 }
 
 void ieee80211_sysfs_deinit(void)
 {
+	ieee80211_unregister_wiphy_cintf();
 	class_unregister(&ieee80211_class);
 }
-- 
1.3.0


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

* [PATCH 3/17] d80211: allow WDS remote to by set by WE
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
  2006-04-21 20:11 ` [PATCH 1/17] d80211: Replace MODULE_PARM with module_param Jiri Benc
  2006-04-21 20:11 ` [PATCH 2/17] d80211: symlinks to wiphy in sysfs Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 4/17] d80211: add IBSS and monitor interface types Jiri Benc
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Setting of address of WDS remote peer wasn't possible by a WE call. Remote
WDS peer can be understood as a remote AP and SIOCSIWAP/SIOCGIWAP are unused
in WDS mode, so let's use them.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   25 +++++--------------------
 net/d80211/ieee80211_i.h     |    3 +--
 net/d80211/ieee80211_ioctl.c |   27 +++++++++++++++++++++++----
 3 files changed, 29 insertions(+), 26 deletions(-)

7ced2ee797d78b7b568be06a02ff3c1c06b25b9d
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index d0bc0bc..f80dffa 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3944,25 +3944,11 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 }
 
 
-int ieee80211_if_update_wds(struct net_device *dev, char *name,
-			    struct ieee80211_if_wds *wds, int locked)
+int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
 {
-	struct net_device *wds_dev = NULL;
 	struct ieee80211_local *local = dev->priv;
-	struct ieee80211_sub_if_data *sdata = NULL;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta;
-	struct list_head *ptr;
-
-	list_for_each(ptr, &local->sub_if_list) {
-		sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (strcmp(name, sdata->dev->name) == 0) {
-			wds_dev = sdata->dev;
-			break;
-		}
-	}
-
-	if (wds_dev == NULL || sdata->type != IEEE80211_SUB_IF_TYPE_WDS)
-		return -ENODEV;
 
 	/* Remove STA entry for the old peer */
 	sta = sta_info_get(local, sdata->u.wds.remote_addr);
@@ -3971,13 +3957,12 @@ int ieee80211_if_update_wds(struct net_d
 		sta_info_free(local, sta, 0);
 	} else {
 		printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
-		       "%s peer " MACSTR "\n",
-		       dev->name, wds_dev->name,
-		       MAC2STR(sdata->u.wds.remote_addr));
+		       "peer " MACSTR "\n",
+		       dev->name, MAC2STR(sdata->u.wds.remote_addr));
 	}
 
 	/* Update WDS link data */
-        memcpy(&sdata->u.wds, wds, sizeof(struct ieee80211_if_wds));
+	memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
 
 	return 0;
 }
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index c217104..ba72466 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -517,8 +517,7 @@ int ieee80211_if_remove_wds(struct net_d
 int ieee80211_if_remove_vlan(struct net_device *dev, const char *name, int locked);
 int ieee80211_if_remove_ap(struct net_device *dev, const char *name, int locked);
 int ieee80211_if_flush(struct net_device *dev, int locked);
-int ieee80211_if_update_wds(struct net_device *dev, char *name,
-			    struct ieee80211_if_wds *wds, int locked);
+int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
 
 /* ieee80211_ioctl.c */
 int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 987f761..71b72fe 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -997,17 +997,27 @@ static int ieee80211_ioctl_update_if(str
         int left = param_len - ((u8 *) pos - (u8 *) param);
 
 	if (param->u.if_info.type == HOSTAP_IF_WDS) {
-		struct ieee80211_if_wds iwds;
 		struct hostapd_if_wds *wds =
 			(struct hostapd_if_wds *) param->u.if_info.data;
+		struct ieee80211_local *local = dev->priv;
+		struct net_device *wds_dev = NULL;
+		struct ieee80211_sub_if_data *sdata;
 
 		if (left < sizeof(struct ieee80211_if_wds))
 			return -EPROTO;
 
-		memcpy(iwds.remote_addr, wds->remote_addr, ETH_ALEN);
+		list_for_each_entry(sdata, &local->sub_if_list, list) {
+			if (strcmp(param->u.if_info.name,
+				   sdata->dev->name) == 0) {
+				wds_dev = sdata->dev;
+				break;
+			}
+		}
 
-		return ieee80211_if_update_wds(dev, param->u.if_info.name,
-					       &iwds, 1);
+		if (wds_dev == NULL || sdata->type != IEEE80211_SUB_IF_TYPE_WDS)
+			return -ENODEV;
+
+		return ieee80211_if_update_wds(wds_dev, wds->remote_addr);
 	} else {
 		return -EOPNOTSUPP;
 	}
@@ -1842,6 +1852,11 @@ static int ieee80211_ioctl_siwap(struct 
 			       "the low-level driver\n", dev->name);
 		}
 		return ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
+	} else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) {
+		if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
+			   ETH_ALEN) == 0)
+			return 0;
+		return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
 	}
 
 	return -EOPNOTSUPP;
@@ -1859,6 +1874,10 @@ static int ieee80211_ioctl_giwap(struct 
 		ap_addr->sa_family = ARPHRD_ETHER;
 		memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
 		return 0;
+	} else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) {
+		ap_addr->sa_family = ARPHRD_ETHER;
+		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
+		return 0;
 	}
 
 	return -EOPNOTSUPP;
-- 
1.3.0


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

* [PATCH 4/17] d80211: add IBSS and monitor interface types
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (2 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 3/17] d80211: allow WDS remote to by set by WE Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 5/17] d80211: non-shared " Jiri Benc
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Add constants for IBSS and monitor interface types. These constants are used
in subsequent patches.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211_i.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

b5f3ee77e4da0c6cbe98000f1380d3df92a949d4
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index ba72466..848afb7 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -259,6 +259,8 @@ #define IEEE80211_AUTH_ALG_LEAP BIT(2)
 #define IEEE80211_SUB_IF_TYPE_AP   0x00000000
 #define IEEE80211_SUB_IF_TYPE_MGMT 0x00000001
 #define IEEE80211_SUB_IF_TYPE_STA  0x00000002
+#define IEEE80211_SUB_IF_TYPE_IBSS 0x00000003
+#define IEEE80211_SUB_IF_TYPE_MNTR 0x00000004
 #define IEEE80211_SUB_IF_TYPE_WDS  0x5A580211
 #define IEEE80211_SUB_IF_TYPE_VLAN 0x00080211
 
-- 
1.3.0


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

* [PATCH 5/17] d80211: non-shared interface types
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (3 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 4/17] d80211: add IBSS and monitor interface types Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 6/17] d80211: remove local->bssid variable Jiri Benc
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

This patch removes "iwmode" variable (local->conf.mode) shared by all
interfaces. Instead, every interface has its own type (STA/IBSS/AP/WDS).

Please note, that
- Actual SIOCSIWMODE ioctl is disabled by this patch and is implemented by
  one of subsequent patches.
- There is no way to ask the driver if given combination of interfaces is
  possible. Again, it is implemented by one of subsequent patches.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |   18 ------
 net/d80211/ieee80211.c       |  120 +++++++++++++++++++-----------------------
 net/d80211/ieee80211_ioctl.c |  103 +++++++++++++++++++++++-------------
 net/d80211/ieee80211_proc.c  |   12 +++-
 net/d80211/ieee80211_sta.c   |   43 ++++++++-------
 5 files changed, 150 insertions(+), 146 deletions(-)

16aa733f49d78c481269c79ad8de190b40665da2
diff --git a/include/net/d80211.h b/include/net/d80211.h
index e4c5ed2..75e8e24 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -242,8 +242,6 @@ struct ieee80211_conf {
 	int freq;			/* MHz */
 	int channel_val;		/* hw specific value for the channel */
 
-	int mode;			/* IW_MODE_ */
-
 	int phymode;			/* MODE_IEEE80211A, .. */
         unsigned int regulatory_domain;
         int adm_status;
@@ -359,22 +357,6 @@ struct ieee80211_scan_conf {
 
 };
 
-#ifndef IW_MODE_ADHOC
-#define IW_MODE_ADHOC 1
-#endif
-
-#ifndef IW_MODE_INFRA
-#define IW_MODE_INFRA 2
-#endif
-
-#ifndef IW_MODE_MASTER
-#define IW_MODE_MASTER 3
-#endif
-
-#ifndef IW_MODE_MONITOR
-#define IW_MODE_MONITOR 6
-#endif
-
 #define IEEE80211_SEQ_COUNTER_RX	0
 #define IEEE80211_SEQ_COUNTER_TX	1
 
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index f80dffa..10c4792 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -868,7 +868,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 	if (likely(tx->u.tx.unicast)) {
 		if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
-			     tx->local->conf.mode != IW_MODE_ADHOC &&
+			     tx->sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
 			     WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_DATA)) {
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 			printk(KERN_DEBUG "%s: dropped data frame to not "
@@ -882,7 +882,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		if (unlikely(WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_DATA &&
 			     tx->local->num_sta == 0 &&
 			     !tx->local->allow_broadcast_always &&
-			     tx->local->conf.mode != IW_MODE_ADHOC)) {
+			     tx->sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)) {
 			/*
 			 * No associated STAs - no need to send multicast
 			 * frames.
@@ -1285,24 +1285,11 @@ static int ieee80211_subif_start_xmit(st
 
 	if (likely(sdata->type == IEEE80211_SUB_IF_TYPE_AP ||
 		   sdata->type == IEEE80211_SUB_IF_TYPE_VLAN)) {
-		if (local->conf.mode == IW_MODE_MASTER) {
-			fc |= WLAN_FC_FROMDS;
-			/* DA BSSID SA */
-			memcpy(hdr.addr1, skb->data, ETH_ALEN);
-			memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
-			memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
-		} else if (local->conf.mode == IW_MODE_INFRA) {
-			fc |= WLAN_FC_TODS;
-			/* BSSID SA DA */
-			memcpy(hdr.addr1, local->bssid, ETH_ALEN);
-			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-			memcpy(hdr.addr3, skb->data, ETH_ALEN);
-		} else if (local->conf.mode == IW_MODE_ADHOC) {
-			/* DA SA BSSID */
-			memcpy(hdr.addr1, skb->data, ETH_ALEN);
-			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-			memcpy(hdr.addr3, local->bssid, ETH_ALEN);
-		}
+		fc |= WLAN_FC_FROMDS;
+		/* DA BSSID SA */
+		memcpy(hdr.addr1, skb->data, ETH_ALEN);
+		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
                 hdrlen = 24;
         } else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) {
                 fc |= WLAN_FC_FROMDS | WLAN_FC_TODS;
@@ -1313,18 +1300,17 @@ static int ieee80211_subif_start_xmit(st
                 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
                 hdrlen = 30;
         } else if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
-		if (local->conf.mode == IW_MODE_INFRA) {
-			fc |= WLAN_FC_TODS;
-			/* BSSID SA DA */
-			memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
-			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-			memcpy(hdr.addr3, skb->data, ETH_ALEN);
-		} else {
-			/* DA SA BSSID */
-			memcpy(hdr.addr1, skb->data, ETH_ALEN);
-			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-			memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);
-		}
+		fc |= WLAN_FC_TODS;
+		/* BSSID SA DA */
+		memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
+		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+		memcpy(hdr.addr3, skb->data, ETH_ALEN);
+		hdrlen = 24;
+	} else if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+		/* DA SA BSSID */
+		memcpy(hdr.addr1, skb->data, ETH_ALEN);
+		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+		memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);
 		hdrlen = 24;
         } else {
                 ret = 0;
@@ -1722,9 +1708,9 @@ int ieee80211_hw_config(struct net_devic
 	int i, ret = 0;
 
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d mode=%d "
+	printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
 	       "phymode=%d\n", local->conf.channel, local->conf.freq,
-	       local->conf.mode, local->conf.phymode);
+	       local->conf.phymode);
 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 	if (local->hw->config)
@@ -1957,7 +1943,8 @@ static struct net_device * ieee80211_sta
 	list_for_each(ptr, &local->sub_if_list) {
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
+		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			continue;
 		if (!multicast &&
 		    memcmp(a1, sdata->dev->dev_addr, ETH_ALEN) != 0)
@@ -1965,7 +1952,7 @@ static struct net_device * ieee80211_sta
 
 		if (memcmp(addr, sdata->u.sta.bssid, ETH_ALEN) == 0 ||
 		    (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0 &&
-		     local->conf.mode == IW_MODE_ADHOC)) {
+		     sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)) {
 			*sta_multicast = multicast;
 			return sdata->dev;
 		}
@@ -2007,7 +1994,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 	u8 dst[ETH_ALEN];
 	u8 src[ETH_ALEN];
         struct sk_buff *skb = rx->skb, *skb2;
-        struct ieee80211_sub_if_data *sdata;
+        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	fc = rx->fc;
 	if (unlikely(WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_DATA))
@@ -2034,7 +2021,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr3, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
-		if (unlikely(local->conf.mode != IW_MODE_MASTER ||
+		if (unlikely(sdata->type != IEEE80211_SUB_IF_TYPE_AP ||
 			     !ieee80211_own_bssid(local, hdr->addr1))) {
 			printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
 			       MACSTR " SA=" MACSTR " DA=" MACSTR ")\n",
@@ -2064,7 +2051,6 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr3, ETH_ALEN);
 
-		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
 		    memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0 ||
 		    memcmp(hdr->addr2, sdata->u.sta.bssid, ETH_ALEN) != 0) {
@@ -2076,7 +2062,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
-		if (local->conf.mode != IW_MODE_ADHOC ||
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS ||
 		    memcmp(hdr->addr3, local->bssid, ETH_ALEN) != 0) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
@@ -2140,8 +2126,8 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		sdata->stats.rx_bytes += skb->len;
         }
 
-	if (local->bridge_packets && sdata->type != IEEE80211_SUB_IF_TYPE_WDS
-	    && sdata->type != IEEE80211_SUB_IF_TYPE_STA) {
+	if (local->bridge_packets && (sdata->type == IEEE80211_SUB_IF_TYPE_AP
+	    || sdata->type == IEEE80211_SUB_IF_TYPE_VLAN)) {
 		if (MULTICAST_ADDR(skb->data)) {
 			/* send multicast frames both to higher layers in
 			 * local net stack and back to the wireless media */
@@ -2672,7 +2658,7 @@ #endif /* IEEE80211_LEDS */
 static ieee80211_txrx_result
 ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
 {
-	if (rx->local->conf.mode == IW_MODE_MONITOR) {
+	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_MNTR) {
 		ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
                                   ieee80211_msg_monitor);
 		return TXRX_QUEUED;
@@ -2711,7 +2697,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 
 	/* Filter out foreign unicast packets when in promiscuous mode.
 	 * FIX: Filter out multicast to foreign BSSID. */
-	if (rx->local->conf.mode == IW_MODE_INFRA &&
+	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_STA &&
 	    !MULTICAST_ADDR(hdr->addr1) &&
 	    !ieee80211_own_addr(rx->dev, hdr->addr1))
 		return TXRX_DROP;
@@ -2727,7 +2713,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 	if (unlikely((WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA ||
 		      (WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_CTRL &&
 		       WLAN_FC_GET_STYPE(rx->fc) == WLAN_FC_STYPE_PSPOLL)) &&
-		     rx->local->conf.mode != IW_MODE_ADHOC &&
+		     rx->sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
 		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
 		if (!(rx->fc & WLAN_FC_FROMDS) && !(rx->fc & WLAN_FC_TODS)) {
 			/* Drop IBSS frames silently. */
@@ -2739,7 +2725,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		return TXRX_QUEUED;
 	}
 
-	if (rx->local->conf.mode == IW_MODE_INFRA)
+	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_STA)
 		always_sta_key = 0;
 	else
 		always_sta_key = 1;
@@ -2815,13 +2801,13 @@ ieee80211_rx_h_sta_process(struct ieee80
 	/* Update last_rx only for IBSS packets which are for the current
 	 * BSSID to avoid keeping the current IBSS network alive in cases where
 	 * other STAs are using different BSSID. */
-	if (rx->local->conf.mode == IW_MODE_ADHOC) {
+	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);
 		if (memcmp(bssid, rx->local->bssid, ETH_ALEN) == 0)
 			sta->last_rx = jiffies;
 	} else
 	if (!MULTICAST_ADDR(hdr->addr1) ||
-	    rx->local->conf.mode == IW_MODE_INFRA) {
+	    rx->sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
 		/* Update last_rx only for unicast frames in order to prevent
 		 * the Probe Request frames (the only broadcast frames from a
 		 * STA in infrastructure mode) from keeping a connection alive.
@@ -2920,7 +2906,7 @@ static ieee80211_txrx_result
 ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
 {
 	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
-	    rx->local->conf.mode != IW_MODE_INFRA) {
+	    rx->sdata->type != IEEE80211_SUB_IF_TYPE_STA) {
 		/* Pass both encrypted and unencrypted EAPOL frames to user
 		 * space for processing. */
 		ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
@@ -2974,7 +2960,8 @@ ieee80211_rx_h_mgmt(struct ieee80211_txr
 {
         struct ieee80211_sub_if_data *sdata;
 	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
 	} else {
 		/* Management frames are sent to hostapd for processing */
@@ -3076,8 +3063,7 @@ static struct net_device * ieee80211_get
 	bssid = ieee80211_get_bssid(hdr, len);
 	if (bssid) {
 		dev = ieee80211_own_bssid(local, bssid);
-		if (!dev && (local->conf.mode == IW_MODE_INFRA ||
-			     local->conf.mode == IW_MODE_ADHOC))
+		if (!dev)
 			dev = ieee80211_sta_bssid(local, bssid, hdr->addr1,
 						  sta_broadcast);
 		if (dev)
@@ -3137,7 +3123,7 @@ static void ieee80211_rx_michael_mic_rep
 	}
 
 	if (rx->local->hw->wep_include_iv &&
-	    rx->local->conf.mode == IW_MODE_MASTER) {
+	    rx->sdata->type == IEEE80211_SUB_IF_TYPE_AP) {
 		int keyidx = ieee80211_wep_get_keyidx(rx->skb);
 		/* AP with Pairwise keys support should never receive Michael
 		 * MIC errors for non-zero keyidx because these are reserved
@@ -3268,26 +3254,27 @@ void __ieee80211_rx(struct net_device *d
 	memset(&rx, 0, sizeof(rx));
 	rx.skb = skb;
 	rx.local = local;
-	if (skb->len >= 16) {
+	if (skb->len >= 16)
 		sta = rx.sta = sta_info_get(local, hdr->addr2);
-		if (unlikely(sta == NULL &&
-			     local->conf.mode == IW_MODE_ADHOC)) {
+	else
+		sta = rx.sta = NULL;
+	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS)) {
+		rx.dev = sta->dev;
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+	} else {
+		rx.dev = ieee80211_get_rx_dev(local, hdr, skb->len,
+					      &sta_broadcast);
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+		if (sta == NULL &&
+		    rx.sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 			u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
-			if (bssid &&
-			    memcmp(bssid, local->bssid, ETH_ALEN) == 0)
+			if (bssid)
 				sta = rx.sta =
 					ieee80211_ibss_add_sta(dev, skb, bssid,
 							       hdr->addr2);
 		}
-	} else
-		sta = rx.sta = NULL;
-        if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS))
-		rx.dev = sta->dev;
-	else
-		rx.dev = ieee80211_get_rx_dev(local, hdr, skb->len,
-					      &sta_broadcast);
+	}
 
-	rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
 	rx.u.rx.status = status;
 	rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0;
 	type = WLAN_FC_GET_TYPE(rx.fc);
@@ -4550,7 +4537,6 @@ int ieee80211_register_hw(struct net_dev
 	if (result < 0)
 		goto fail_sysfs;
 
-	local->conf.mode = IW_MODE_MASTER;
 	local->conf.beacon_int = 1000;
 
 	ieee80211_update_hw(dev, hw);	/* Don't care about the result. */
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 71b72fe..8f0aad5 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -541,8 +541,8 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 	 * optimized by using non-default keys (at least with Atheros ar521x).
 	 */
 	if (!sta && alg == ALG_WEP && !local->default_wep_only &&
-	    local->conf.mode != IW_MODE_ADHOC &&
-	    local->conf.mode != IW_MODE_INFRA) {
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
+	    sdata->type != IEEE80211_SUB_IF_TYPE_AP) {
 		try_hwaccel = 0;
 	}
 
@@ -1052,7 +1052,8 @@ static int ieee80211_ioctl_sta_get_state
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 		return -EINVAL;
 	param->u.sta_get_state.state = sdata->u.sta.state;
 	return 0;
@@ -1065,15 +1066,14 @@ static int ieee80211_ioctl_mlme(struct n
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 		return -EINVAL;
 	switch (param->u.mlme.cmd) {
 	case MLME_STA_DEAUTH:
-		ieee80211_sta_deauthenticate(dev, param->u.mlme.reason_code);
-		break;
+		return ieee80211_sta_deauthenticate(dev, param->u.mlme.reason_code);
 	case MLME_STA_DISASSOC:
-		ieee80211_sta_disassociate(dev, param->u.mlme.reason_code);
-		break;
+		return ieee80211_sta_disassociate(dev, param->u.mlme.reason_code);
 	}
 	return 0;
 }
@@ -1126,7 +1126,8 @@ static int ieee80211_set_gen_ie(struct n
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
 		return ieee80211_sta_set_extra_ie(dev, ie, len);
 
 	kfree(local->conf.generic_elem);
@@ -1654,16 +1655,11 @@ static int ieee80211_init_client(struct 
 }
 
 
-static int ieee80211_is_client_mode(int iw_mode)
-{
-	return (iw_mode == IW_MODE_INFRA || iw_mode == IW_MODE_ADHOC);
-}
-
-
 static int ieee80211_ioctl_siwmode(struct net_device *dev,
 				   struct iw_request_info *info,
 				   __u32 *mode, char *extra)
 {
+#if 0
 	struct ieee80211_local *local = dev->priv;
 
 	if (!ieee80211_is_client_mode(local->conf.mode) &&
@@ -1689,6 +1685,9 @@ static int ieee80211_ioctl_siwmode(struc
 	}
 	local->conf.mode = *mode;
 	return ieee80211_hw_config(dev);
+#else
+	return -EOPNOTSUPP;
+#endif
 }
 
 
@@ -1696,17 +1695,32 @@ static int ieee80211_ioctl_giwmode(struc
 				   struct iw_request_info *info,
 				   __u32 *mode, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
-		if (local->conf.mode == IW_MODE_ADHOC)
-			*mode = IW_MODE_ADHOC;
-		else
-			*mode = IW_MODE_INFRA;
-	} else
-		*mode = local->conf.mode;
+	switch (sdata->type) {
+	case IEEE80211_SUB_IF_TYPE_AP:
+		*mode = IW_MODE_MASTER;
+		break;
+	case IEEE80211_SUB_IF_TYPE_STA:
+		*mode = IW_MODE_INFRA;
+		break;
+	case IEEE80211_SUB_IF_TYPE_IBSS:
+		*mode = IW_MODE_ADHOC;
+		break;
+	case IEEE80211_SUB_IF_TYPE_MNTR:
+		*mode = IW_MODE_MONITOR;
+		break;
+	case IEEE80211_SUB_IF_TYPE_WDS:
+		*mode = IW_MODE_REPEAT;
+		break;
+	case IEEE80211_SUB_IF_TYPE_VLAN:
+		*mode = IW_MODE_SECOND;		/* FIXME */
+		break;
+	default:
+		*mode = IW_MODE_AUTO;
+		break;
+	}
 	return 0;
 }
 
@@ -1793,7 +1807,8 @@ static int ieee80211_ioctl_siwessid(stru
 		len--;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
 		return ieee80211_sta_set_ssid(dev, ssid, len);
 
 	kfree(local->conf.ssid);
@@ -1816,7 +1831,8 @@ static int ieee80211_ioctl_giwessid(stru
 
 	struct ieee80211_sub_if_data *sdata;
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		int res = ieee80211_sta_get_ssid(dev, ssid, &len);
 		if (res == 0)
 			data->length = len;
@@ -1840,7 +1856,8 @@ static int ieee80211_ioctl_siwap(struct 
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		int changed_bssid = 0;
 		if (memcmp(local->conf.client_bssid, (u8 *) &ap_addr->sa_data,
 			   ETH_ALEN) != 0)
@@ -1870,7 +1887,8 @@ static int ieee80211_ioctl_giwap(struct 
         struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		ap_addr->sa_family = ARPHRD_ETHER;
 		memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
 		return 0;
@@ -2288,7 +2306,8 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_AP_AUTH_ALGS:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 			sdata->u.sta.auth_algs = value;
 		} else
 			ret = -EOPNOTSUPP;
@@ -2464,7 +2483,8 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_MIXED_CELL:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.mixed_cell = !!value;
@@ -2482,13 +2502,14 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_CREATE_IBSS:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.create_ibss = !!value;
 		break;
 	case PRISM2_PARAM_WMM_ENABLED:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.wmm_enabled = !!value;
@@ -2529,7 +2550,8 @@ static int ieee80211_ioctl_get_prism2_pa
 		break;
 
 	case PRISM2_PARAM_AP_AUTH_ALGS:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 			*param = sdata->u.sta.auth_algs;
 		} else
 			ret = -EOPNOTSUPP;
@@ -2653,14 +2675,15 @@ static int ieee80211_ioctl_get_prism2_pa
 		break;
 
 	case PRISM2_PARAM_CREATE_IBSS:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			*param = !!sdata->u.sta.create_ibss;
 		break;
 
 	case PRISM2_PARAM_MIXED_CELL:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			*param = !!sdata->u.sta.mixed_cell;
@@ -2673,7 +2696,8 @@ static int ieee80211_ioctl_get_prism2_pa
 			*param = sdata->u.sta.key_mgmt;
 		break;
 	case PRISM2_PARAM_WMM_ENABLED:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			*param = !!sdata->u.sta.wmm_enabled;
@@ -2715,7 +2739,8 @@ static int ieee80211_ioctl_siwmlme(struc
 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 		return -EINVAL;
 
 	switch (mlme->cmd) {
@@ -2859,7 +2884,8 @@ static int ieee80211_ioctl_siwauth(struc
 		}
 		break;
 	case IW_AUTH_80211_AUTH_ALG:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
 			sdata->u.sta.auth_algs = data->value;
 		else
 			ret = -EOPNOTSUPP;
@@ -2885,7 +2911,8 @@ static int ieee80211_ioctl_giwauth(struc
 
 	switch (data->flags & IW_AUTH_INDEX) {
 	case IW_AUTH_80211_AUTH_ALG:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
 			data->value = sdata->u.sta.auth_algs;
 		else
 			ret = -EOPNOTSUPP;
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index 5d77c2a..3709494 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -110,10 +110,13 @@ static char * ieee80211_proc_sub_if_ap(c
 }
 
 
-static char * ieee80211_proc_sub_if_sta(char *p,
+static char * ieee80211_proc_sub_if_sta(char *p, int ibss,
 					struct ieee80211_if_sta *ifsta)
 {
-	p += sprintf(p, "type=sta\n");
+	if (ibss)
+		p += sprintf(p, "type=ibss\n");
+	else
+		p += sprintf(p, "type=sta\n");
 	p += sprintf(p,
 		     "state=%d\n"
 		     "bssid=" MACSTR "\n"
@@ -176,7 +179,10 @@ static char * ieee80211_proc_sub_if(char
 		p += sprintf(p, "vlan.id=%d\n", sdata->u.vlan.id);
 		break;
 	case IEEE80211_SUB_IF_TYPE_STA:
-		p = ieee80211_proc_sub_if_sta(p, &sdata->u.sta);
+		p = ieee80211_proc_sub_if_sta(p, 0, &sdata->u.sta);
+		break;
+	case IEEE80211_SUB_IF_TYPE_IBSS:
+		p = ieee80211_proc_sub_if_sta(p, 1, &sdata->u.sta);
 		break;
 	}
 	p += sprintf(p, "channel_use=%d\n", sdata->channel_use);
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 5a59750..9972b98 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -859,11 +859,11 @@ static void ieee80211_rx_mgmt_auth(struc
 				   size_t len,
 				   struct ieee80211_rx_status *rx_status)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	u16 auth_alg, auth_transaction, status_code;
 
 	if (ifsta->state != IEEE80211_AUTHENTICATE &&
-	    local->conf.mode != IW_MODE_ADHOC) {
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS) {
 		printk(KERN_DEBUG "%s: authentication frame received from "
 		       MACSTR ", but not in authenticate state - ignored\n",
 		       dev->name, MAC2STR(mgmt->sa));
@@ -877,7 +877,7 @@ static void ieee80211_rx_mgmt_auth(struc
 		return;
 	}
 
-	if (local->conf.mode != IW_MODE_ADHOC &&
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
 	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
 		printk(KERN_DEBUG "%s: authentication frame received from "
 		       "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - "
@@ -886,7 +886,7 @@ static void ieee80211_rx_mgmt_auth(struc
 		return;
 	}
 
-	if (local->conf.mode == IW_MODE_ADHOC &&
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
 	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
 		printk(KERN_DEBUG "%s: authentication frame received from "
 		       "unknown BSSID (SA=" MACSTR " BSSID=" MACSTR ") - "
@@ -904,7 +904,7 @@ static void ieee80211_rx_mgmt_auth(struc
 	       dev->name, MAC2STR(mgmt->sa), auth_alg,
 	       auth_transaction, status_code);
 
-	if (local->conf.mode == IW_MODE_ADHOC) {
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		/* IEEE 802.11 standard does not require authentication in IBSS
 		 * networks and most implementations do not seem to use it.
 		 * However, try to reply to authentication attempts if someone
@@ -1341,7 +1341,7 @@ static void ieee80211_rx_bss_info(struct
 	int channel, invalid = 0, clen;
 	struct ieee80211_sta_bss *bss;
 	struct sta_info *sta;
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	u64 timestamp;
 	u8 *pos;
 
@@ -1364,7 +1364,7 @@ #endif
 		((u64) pos[3] << 24) | ((u64) pos[2] << 16) |
 		((u64) pos[1] << 8) | ((u64) pos[0]);
 
-	if (local->conf.mode == IW_MODE_ADHOC && beacon &&
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && beacon &&
 	    memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) {
 #ifdef IEEE80211_IBSS_DEBUG
 		static unsigned long last_tsf_debug = 0;
@@ -1388,11 +1388,9 @@ #endif /* IEEE80211_IBSS_DEBUG */
 				   &elems) == ParseFailed)
 		invalid = 1;
 
-	if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates &&
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && elems.supp_rates &&
 	    memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 &&
-	    (sta = sta_info_get(local, mgmt->sa)) &&
-	    (sdata = IEEE80211_DEV_TO_SUB_IF(dev)) &&
-	    sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+	    (sta = sta_info_get(local, mgmt->sa))) {
 		struct ieee80211_rate *rates;
 		size_t num_rates;
 		u32 supp_rates, prev_rates;
@@ -1647,12 +1645,13 @@ static void ieee80211_rx_mgmt_probe_req(
 					struct ieee80211_rx_status *rx_status)
 {
 	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	int tx_last_beacon;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *resp;
 	u8 *pos, *end;
 
-	if (local->conf.mode != IW_MODE_ADHOC ||
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS ||
 	    ifsta->state != IEEE80211_IBSS_JOINED ||
 	    len < 24 + 2 || ifsta->probe_resp == NULL)
 		return;
@@ -1866,7 +1865,8 @@ void ieee80211_sta_timer(unsigned long p
 
 	dev = (struct net_device *) ptr;
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) {
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS) {
 		printk(KERN_DEBUG "%s: ieee80211_sta_timer: non-STA interface "
 		       "(type=%d)\n", dev->name, sdata->type);
 		return;
@@ -1911,8 +1911,9 @@ static void ieee80211_sta_new_auth(struc
 				   struct ieee80211_if_sta *ifsta)
 {
 	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	if (local->conf.mode != IW_MODE_INFRA)
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
 		return;
 
 	if (local->hw->reset_tsf) {
@@ -2318,7 +2319,7 @@ int ieee80211_sta_set_ssid(struct net_de
 	ifsta->ssid_len = len;
 
 	ifsta->ssid_set = 1;
-	if (local->conf.mode == IW_MODE_ADHOC && !ifsta->bssid_set) {
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && !ifsta->bssid_set) {
 		ifsta->ibss_join_req = jiffies;
 		ifsta->state = IEEE80211_IBSS_SEARCH;
 		return ieee80211_sta_find_ibss(dev, ifsta);
@@ -2351,7 +2352,7 @@ int ieee80211_sta_set_bssid(struct net_d
 	ifsta = &sdata->u.sta;
 
 	memcpy(ifsta->bssid, bssid, ETH_ALEN);
-	if (local->conf.mode == IW_MODE_ADHOC)
+	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
 		memcpy(local->bssid, bssid, ETH_ALEN);
 
 	if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
@@ -2417,6 +2418,7 @@ static void ieee80211_sta_scan_timer(uns
 {
 	struct net_device *dev = (struct net_device *) ptr;
 	struct ieee80211_local *local = dev->priv;
+        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_hw_modes *mode;
 	struct ieee80211_channel *chan;
 	int skip;
@@ -2441,7 +2443,7 @@ static void ieee80211_sta_scan_timer(uns
 			local->last_scan_completed = jiffies;
 			memset(&wrqu, 0, sizeof(wrqu));
 			wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
-			if (local->conf.mode == IW_MODE_ADHOC) {
+			if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 				struct ieee80211_sub_if_data *sdata =
 					IEEE80211_DEV_TO_SUB_IF(dev);
 				struct ieee80211_if_sta *ifsta = &sdata->u.sta;
@@ -2455,7 +2457,7 @@ static void ieee80211_sta_scan_timer(uns
 		skip = !(local->hw_modes & (1 << mode->mode));
 		chan = &mode->channels[local->scan_channel_idx];
 		if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
-		    (local->conf.mode == IW_MODE_ADHOC &&
+		    (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS &&
 		     !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
 		    (local->hw_modes & (1 << MODE_IEEE80211G) &&
 		     mode->mode == MODE_IEEE80211B && local->scan_skip_11b))
@@ -2801,7 +2803,7 @@ struct sta_info * ieee80211_ibss_add_sta
 	spin_lock_bh(&local->sub_if_lock);
 	list_for_each(ptr, &local->sub_if_list) {
 		sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA &&
+		if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS &&
 		    memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
 			sta_dev = sdata->dev;
 			break;
@@ -2837,7 +2839,8 @@ int ieee80211_sta_deauthenticate(struct 
 	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
 	       dev->name, reason);
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
 		return -EINVAL;
 
 	ieee80211_send_deauth(dev, ifsta, reason);
-- 
1.3.0


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

* [PATCH 6/17] d80211: remove local->bssid variable
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (4 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 5/17] d80211: non-shared " Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 7/17] d80211: rename IEEE80211_SUB_IF_TYPE_ constants Jiri Benc
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

BSSID shouldn't be common for all interfaces.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c     |    4 ++--
 net/d80211/ieee80211_i.h   |    1 -
 net/d80211/ieee80211_sta.c |    8 ++------
 3 files changed, 4 insertions(+), 9 deletions(-)

78d82ec5d0282693656a09add989460775d56bbd
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 10c4792..362c231 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2063,7 +2063,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
 		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS ||
-		    memcmp(hdr->addr3, local->bssid, ETH_ALEN) != 0) {
+		    memcmp(hdr->addr3, sdata->u.sta.bssid, ETH_ALEN) != 0) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
 				       MACSTR " SA=" MACSTR " BSSID=" MACSTR
@@ -2803,7 +2803,7 @@ ieee80211_rx_h_sta_process(struct ieee80
 	 * other STAs are using different BSSID. */
 	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);
-		if (memcmp(bssid, rx->local->bssid, ETH_ALEN) == 0)
+		if (memcmp(bssid, rx->sdata->u.sta.bssid, ETH_ALEN) == 0)
 			sta->last_rx = jiffies;
 	} else
 	if (!MULTICAST_ADDR(hdr->addr1) ||
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 848afb7..8fe1dd1 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -433,7 +433,6 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */
         u32 stat_time;
         struct timer_list stat_timer;
 
-	u8 bssid[ETH_ALEN]; /* BSSID for STA modes (Adhoc/Managed) */
         struct timer_list rate_limit_timer;
         u32 rate_limit;
         u32 rate_limit_burst;
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 9972b98..5df6734 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -1365,7 +1365,7 @@ #endif
 		((u64) pos[1] << 8) | ((u64) pos[0]);
 
 	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && beacon &&
-	    memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) {
+	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
 #ifdef IEEE80211_IBSS_DEBUG
 		static unsigned long last_tsf_debug = 0;
 		u64 tsf;
@@ -1389,7 +1389,7 @@ #endif /* IEEE80211_IBSS_DEBUG */
 		invalid = 1;
 
 	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && elems.supp_rates &&
-	    memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 &&
+	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
 	    (sta = sta_info_get(local, mgmt->sa))) {
 		struct ieee80211_rate *rates;
 		size_t num_rates;
@@ -1990,7 +1990,6 @@ static int ieee80211_sta_join_ibss(struc
 		local->hw->reset_tsf(local->mdev);
 	}
 	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
-	memcpy(local->bssid, bss->bssid, ETH_ALEN);
 	memcpy(local->conf.client_bssid, bss->bssid, ETH_ALEN);
 
 	local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
@@ -2344,7 +2343,6 @@ int ieee80211_sta_get_ssid(struct net_de
 
 int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
 {
-	struct ieee80211_local *local = dev->priv;
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_sta *ifsta;
 
@@ -2352,8 +2350,6 @@ int ieee80211_sta_set_bssid(struct net_d
 	ifsta = &sdata->u.sta;
 
 	memcpy(ifsta->bssid, bssid, ETH_ALEN);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
-		memcpy(local->bssid, bssid, ETH_ALEN);
 
 	if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
 		ifsta->bssid_set = 0;
-- 
1.3.0


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

* [PATCH 7/17] d80211: rename IEEE80211_SUB_IF_TYPE_ constants
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (5 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 6/17] d80211: remove local->bssid variable Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 8/17] d80211: ask driver for allowed iface combinations Jiri Benc
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

As we're going to expose IEEE80211_SUB_IF_TYPE_* constants to drivers, the
prefix IEEE80211_SUB_IF_TYPE_ is no longer appropriate. The constants are
going to mean the type of 802.11 interface, not the type of sub-interface
structure (which is not visible to drivers at all).

This patch renames them to IEEE80211_IF_TYPE_*.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   98 +++++++++++++++++-------------------
 net/d80211/ieee80211_i.h     |   14 +++--
 net/d80211/ieee80211_ioctl.c |  114 +++++++++++++++++++++---------------------
 net/d80211/ieee80211_proc.c  |   10 ++--
 net/d80211/ieee80211_sta.c   |   40 +++++++--------
 net/d80211/wme.c             |    2 -
 6 files changed, 137 insertions(+), 141 deletions(-)

6369196531f5cb19227491f2497b043272e2ab88
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 362c231..fae9d64 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -326,7 +326,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
 
 	memset(&extra, 0, sizeof(extra));
 	extra.mgmt_data = tx->sdata &&
-		tx->sdata->type == IEEE80211_SUB_IF_TYPE_MGMT;
+		tx->sdata->type == IEEE80211_IF_TYPE_MGMT;
 	extra.ethertype = tx->ethertype;
 	extra.startidx  = 0;
 	extra.endidx    = tx->local->num_curr_rates;
@@ -868,7 +868,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 	if (likely(tx->u.tx.unicast)) {
 		if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
-			     tx->sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
+			     tx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
 			     WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_DATA)) {
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 			printk(KERN_DEBUG "%s: dropped data frame to not "
@@ -882,7 +882,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		if (unlikely(WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_DATA &&
 			     tx->local->num_sta == 0 &&
 			     !tx->local->allow_broadcast_always &&
-			     tx->sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)) {
+			     tx->sdata->type != IEEE80211_IF_TYPE_IBSS)) {
 			/*
 			 * No associated STAs - no need to send multicast
 			 * frames.
@@ -925,7 +925,7 @@ static void purge_old_ps_buffers(struct 
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
 		if (sdata->dev == local->mdev ||
-		    sdata->type != IEEE80211_SUB_IF_TYPE_AP)
+		    sdata->type != IEEE80211_IF_TYPE_AP)
 			continue;
 		ap = &sdata->u.ap;
 		skb = skb_dequeue(&ap->ps_bc_buf);
@@ -963,7 +963,7 @@ ieee80211_tx_h_multicast_ps_buf(struct i
 	/* If any of the associated stations is in power save mode,
 	 * the frame is buffered to be sent after DTIM beacon frame */
 	if (tx->local->hw->host_broadcast_ps_buffering &&
-	    tx->sdata->type != IEEE80211_SUB_IF_TYPE_WDS &&
+	    tx->sdata->type != IEEE80211_IF_TYPE_WDS &&
 	    tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) &&
 	    !(tx->fc & WLAN_FC_ORDER)) {
 		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -1231,7 +1231,7 @@ static int ieee80211_master_start_xmit(s
 	control.queue = pkt_data->queue;
 
 	ret = ieee80211_tx(dev, skb, &control,
-			   control.sdata->type == IEEE80211_SUB_IF_TYPE_MGMT);
+			   control.sdata->type == IEEE80211_IF_TYPE_MGMT);
 
         return ret;
 }
@@ -1283,15 +1283,15 @@ static int ieee80211_subif_start_xmit(st
 	/* TODO: handling for 802.1x authorized/unauthorized port */
 	fc = (WLAN_FC_TYPE_DATA << 2) | (WLAN_FC_STYPE_DATA << 4);
 
-	if (likely(sdata->type == IEEE80211_SUB_IF_TYPE_AP ||
-		   sdata->type == IEEE80211_SUB_IF_TYPE_VLAN)) {
+	if (likely(sdata->type == IEEE80211_IF_TYPE_AP ||
+		   sdata->type == IEEE80211_IF_TYPE_VLAN)) {
 		fc |= WLAN_FC_FROMDS;
 		/* DA BSSID SA */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
 		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
 		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
                 hdrlen = 24;
-        } else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) {
+        } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
                 fc |= WLAN_FC_FROMDS | WLAN_FC_TODS;
 		/* RA TA DA SA */
                 memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
@@ -1299,14 +1299,14 @@ static int ieee80211_subif_start_xmit(st
                 memcpy(hdr.addr3, skb->data, ETH_ALEN);
                 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
                 hdrlen = 30;
-        } else if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+        } else if (sdata->type == IEEE80211_IF_TYPE_STA) {
 		fc |= WLAN_FC_TODS;
 		/* BSSID SA DA */
 		memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
 		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
 		memcpy(hdr.addr3, skb->data, ETH_ALEN);
 		hdrlen = 24;
-	} else if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	} else if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		/* DA SA BSSID */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
 		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
@@ -1879,7 +1879,7 @@ ieee80211_get_wds_dev(struct ieee80211_l
 	list_for_each(ptr, &local->sub_if_list)	{
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS &&
+		if (sdata->type == IEEE80211_IF_TYPE_WDS &&
 		    memcmp(addr, sdata->u.wds.remote_addr, ETH_ALEN) == 0)
 			return sdata->dev;
 	}
@@ -1943,8 +1943,8 @@ static struct net_device * ieee80211_sta
 	list_for_each(ptr, &local->sub_if_list) {
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
-		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			continue;
 		if (!multicast &&
 		    memcmp(a1, sdata->dev->dev_addr, ETH_ALEN) != 0)
@@ -1952,7 +1952,7 @@ static struct net_device * ieee80211_sta
 
 		if (memcmp(addr, sdata->u.sta.bssid, ETH_ALEN) == 0 ||
 		    (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0 &&
-		     sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)) {
+		     sdata->type == IEEE80211_IF_TYPE_IBSS)) {
 			*sta_multicast = multicast;
 			return sdata->dev;
 		}
@@ -2021,7 +2021,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr3, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
-		if (unlikely(sdata->type != IEEE80211_SUB_IF_TYPE_AP ||
+		if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP ||
 			     !ieee80211_own_bssid(local, hdr->addr1))) {
 			printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
 			       MACSTR " SA=" MACSTR " DA=" MACSTR ")\n",
@@ -2051,7 +2051,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr3, ETH_ALEN);
 
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
 		    memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0 ||
 		    memcmp(hdr->addr2, sdata->u.sta.bssid, ETH_ALEN) != 0) {
 			return TXRX_DROP;
@@ -2062,7 +2062,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS ||
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS ||
 		    memcmp(hdr->addr3, sdata->u.sta.bssid, ETH_ALEN) != 0) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
@@ -2126,8 +2126,8 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		sdata->stats.rx_bytes += skb->len;
         }
 
-	if (local->bridge_packets && (sdata->type == IEEE80211_SUB_IF_TYPE_AP
-	    || sdata->type == IEEE80211_SUB_IF_TYPE_VLAN)) {
+	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
+	    || sdata->type == IEEE80211_IF_TYPE_VLAN)) {
 		if (MULTICAST_ADDR(skb->data)) {
 			/* send multicast frames both to higher layers in
 			 * local net stack and back to the wireless media */
@@ -2658,7 +2658,7 @@ #endif /* IEEE80211_LEDS */
 static ieee80211_txrx_result
 ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
 {
-	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_MNTR) {
+	if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) {
 		ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
                                   ieee80211_msg_monitor);
 		return TXRX_QUEUED;
@@ -2697,7 +2697,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 
 	/* Filter out foreign unicast packets when in promiscuous mode.
 	 * FIX: Filter out multicast to foreign BSSID. */
-	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_STA &&
+	if (rx->sdata->type == IEEE80211_IF_TYPE_STA &&
 	    !MULTICAST_ADDR(hdr->addr1) &&
 	    !ieee80211_own_addr(rx->dev, hdr->addr1))
 		return TXRX_DROP;
@@ -2713,7 +2713,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 	if (unlikely((WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA ||
 		      (WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_CTRL &&
 		       WLAN_FC_GET_STYPE(rx->fc) == WLAN_FC_STYPE_PSPOLL)) &&
-		     rx->sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
+		     rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
 		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
 		if (!(rx->fc & WLAN_FC_FROMDS) && !(rx->fc & WLAN_FC_TODS)) {
 			/* Drop IBSS frames silently. */
@@ -2725,7 +2725,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		return TXRX_QUEUED;
 	}
 
-	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_STA)
+	if (rx->sdata->type == IEEE80211_IF_TYPE_STA)
 		always_sta_key = 0;
 	else
 		always_sta_key = 1;
@@ -2801,13 +2801,13 @@ ieee80211_rx_h_sta_process(struct ieee80
 	/* Update last_rx only for IBSS packets which are for the current
 	 * BSSID to avoid keeping the current IBSS network alive in cases where
 	 * other STAs are using different BSSID. */
-	if (rx->sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);
 		if (memcmp(bssid, rx->sdata->u.sta.bssid, ETH_ALEN) == 0)
 			sta->last_rx = jiffies;
 	} else
 	if (!MULTICAST_ADDR(hdr->addr1) ||
-	    rx->sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+	    rx->sdata->type == IEEE80211_IF_TYPE_STA) {
 		/* Update last_rx only for unicast frames in order to prevent
 		 * the Probe Request frames (the only broadcast frames from a
 		 * STA in infrastructure mode) from keeping a connection alive.
@@ -2906,7 +2906,7 @@ static ieee80211_txrx_result
 ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
 {
 	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
-	    rx->sdata->type != IEEE80211_SUB_IF_TYPE_STA) {
+	    rx->sdata->type != IEEE80211_IF_TYPE_STA) {
 		/* Pass both encrypted and unencrypted EAPOL frames to user
 		 * space for processing. */
 		ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status,
@@ -2960,8 +2960,8 @@ ieee80211_rx_h_mgmt(struct ieee80211_txr
 {
         struct ieee80211_sub_if_data *sdata;
 	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
 	} else {
 		/* Management frames are sent to hostapd for processing */
@@ -3123,7 +3123,7 @@ static void ieee80211_rx_michael_mic_rep
 	}
 
 	if (rx->local->hw->wep_include_iv &&
-	    rx->sdata->type == IEEE80211_SUB_IF_TYPE_AP) {
+	    rx->sdata->type == IEEE80211_IF_TYPE_AP) {
 		int keyidx = ieee80211_wep_get_keyidx(rx->skb);
 		/* AP with Pairwise keys support should never receive Michael
 		 * MIC errors for non-zero keyidx because these are reserved
@@ -3198,7 +3198,7 @@ static void ieee80211_sta_rx_broadcast(s
 	list_for_each(ptr, &local->sub_if_list) {
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
 		    (memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) != 0 &&
 		     !(bssid[0] & 0x01)))
 			continue;
@@ -3266,7 +3266,7 @@ void __ieee80211_rx(struct net_device *d
 					      &sta_broadcast);
 		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
 		if (sta == NULL &&
-		    rx.sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+		    rx.sdata->type == IEEE80211_IF_TYPE_IBSS) {
 			u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
 			if (bssid)
 				sta = rx.sta =
@@ -3868,13 +3868,13 @@ static struct net_device *ieee80211_if_a
 	wds_dev->tx_queue_len = 0;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(wds_dev);
-	sdata->type = IEEE80211_SUB_IF_TYPE_AP;
+	sdata->type = IEEE80211_IF_TYPE_AP;
         sdata->master = local->mdev;
         sdata->dev = wds_dev;
 	sdata->local = local;
 	memset(&sdata->stats, 0, sizeof(struct net_device_stats));
 	sdata_parent = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata_parent->type == IEEE80211_SUB_IF_TYPE_AP)
+	if (sdata_parent->type == IEEE80211_IF_TYPE_AP)
 		sdata->bss = &sdata_parent->u.ap;
 	else {
 		printk(KERN_DEBUG "%s: could not set BSS pointer for new "
@@ -3916,7 +3916,7 @@ int ieee80211_if_add_wds(struct net_devi
                 return -ENOANO;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(wds_dev);
-        sdata->type = IEEE80211_SUB_IF_TYPE_WDS;
+        sdata->type = IEEE80211_IF_TYPE_WDS;
         memcpy(&sdata->u.wds, wds, sizeof(struct ieee80211_if_wds));
 
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
@@ -3983,7 +3983,7 @@ int ieee80211_if_add_vlan(struct net_dev
                 return -ENOANO;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(vlan_dev);
-        sdata->type = IEEE80211_SUB_IF_TYPE_VLAN;
+        sdata->type = IEEE80211_IF_TYPE_VLAN;
 	ieee80211_proc_init_virtual(vlan_dev);
         return 0;
 }
@@ -3991,7 +3991,7 @@ int ieee80211_if_add_vlan(struct net_dev
 
 static void ieee80211_if_ap_init(struct ieee80211_sub_if_data *sdata)
 {
-	sdata->type = IEEE80211_SUB_IF_TYPE_AP;
+	sdata->type = IEEE80211_IF_TYPE_AP;
 	sdata->u.ap.dtim_period = 2;
 	sdata->u.ap.force_unicast_rateidx = -1;
 	sdata->u.ap.max_ratectrl_rateidx = -1;
@@ -4072,7 +4072,7 @@ int ieee80211_if_add_sta(struct net_devi
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(sta_dev);
 	ifsta = &sdata->u.sta;
-	sdata->type = IEEE80211_SUB_IF_TYPE_STA;
+	sdata->type = IEEE80211_IF_TYPE_STA;
 	ieee80211_proc_init_virtual(sta_dev);
 
 	spin_lock_bh(&local->sub_if_lock);
@@ -4131,7 +4131,7 @@ #endif
 	}
 
 	switch (sdata->type) {
-	case IEEE80211_SUB_IF_TYPE_AP:
+	case IEEE80211_IF_TYPE_AP:
 		/* Remove all virtual interfaces that use this BSS
 		 * as their sdata->bss */
 		list_for_each_safe(ptr, n, &local->sub_if_list) {
@@ -4177,7 +4177,7 @@ #endif
 		}
 
 		break;
-	case IEEE80211_SUB_IF_TYPE_WDS:
+	case IEEE80211_IF_TYPE_WDS:
 		sta = sta_info_get(local, sdata->u.wds.remote_addr);
 		if (sta) {
 			sta_info_release(local, sta);
@@ -4189,7 +4189,7 @@ #ifdef CONFIG_D80211_VERBOSE_DEBUG
 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		}
 		break;
-	case IEEE80211_SUB_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_STA:
 		del_timer_sync(&sdata->u.sta.timer);
 		if (local->scan_timer.data == (unsigned long) sdata->dev)
 			del_timer_sync(&local->scan_timer);
@@ -4258,32 +4258,28 @@ static int ieee80211_if_remove(struct ne
 int ieee80211_if_remove_wds(struct net_device *dev, const char *name,
 			    int locked)
 {
-        return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_WDS,
-				   locked);
+        return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_WDS, locked);
 }
 
 
 int ieee80211_if_remove_vlan(struct net_device *dev, const char *name,
 			     int locked)
 {
-        return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_VLAN,
-				   locked);
+        return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_VLAN, locked);
 }
 
 
 int ieee80211_if_remove_ap(struct net_device *dev, const char *name,
 			   int locked)
 {
-	return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_AP,
-				   locked);
+	return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_AP, locked);
 }
 
 
 int ieee80211_if_remove_sta(struct net_device *dev, const char *name,
 			    int locked)
 {
-	return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_STA,
-				   locked);
+	return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_STA, locked);
 }
 
 
@@ -4469,7 +4465,7 @@ struct net_device *ieee80211_alloc_hw(si
 	sprintf(apdev->name, "%sap", dev->name);
 
         sdata = IEEE80211_DEV_TO_SUB_IF(apdev);
-        sdata->type = IEEE80211_SUB_IF_TYPE_MGMT;
+        sdata->type = IEEE80211_IF_TYPE_MGMT;
         sdata->dev = apdev;
         sdata->master = mdev;
         sdata->local = local;
@@ -4490,7 +4486,7 @@ struct net_device *ieee80211_alloc_hw(si
 	sprintf(mdev->name, "%s.11", dev->name);
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
-	sdata->type = IEEE80211_SUB_IF_TYPE_AP;
+	sdata->type = IEEE80211_IF_TYPE_AP;
         sdata->dev = mdev;
         sdata->master = mdev;
         sdata->local = local;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 8fe1dd1..9d18c71 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -256,13 +256,13 @@ #define IEEE80211_AUTH_ALG_LEAP BIT(2)
 };
 
 
-#define IEEE80211_SUB_IF_TYPE_AP   0x00000000
-#define IEEE80211_SUB_IF_TYPE_MGMT 0x00000001
-#define IEEE80211_SUB_IF_TYPE_STA  0x00000002
-#define IEEE80211_SUB_IF_TYPE_IBSS 0x00000003
-#define IEEE80211_SUB_IF_TYPE_MNTR 0x00000004
-#define IEEE80211_SUB_IF_TYPE_WDS  0x5A580211
-#define IEEE80211_SUB_IF_TYPE_VLAN 0x00080211
+#define IEEE80211_IF_TYPE_AP   0x00000000
+#define IEEE80211_IF_TYPE_MGMT 0x00000001
+#define IEEE80211_IF_TYPE_STA  0x00000002
+#define IEEE80211_IF_TYPE_IBSS 0x00000003
+#define IEEE80211_IF_TYPE_MNTR 0x00000004
+#define IEEE80211_IF_TYPE_WDS  0x5A580211
+#define IEEE80211_IF_TYPE_VLAN 0x00080211
 
 struct ieee80211_sub_if_data {
         struct list_head list;
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 8f0aad5..2fd910d 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -64,7 +64,7 @@ static int ieee80211_ioctl_set_beacon(st
 		return -EINVAL;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_AP)
+	if (sdata->type != IEEE80211_IF_TYPE_AP)
 		return -EINVAL;
 	ap = &sdata->u.ap;
 
@@ -499,11 +499,11 @@ static int ieee80211_set_encryption(stru
 		 * must be used. This should be done automatically
 		 * based on configured station devices. For the time
 		 * being, this can be only set at compile time. */
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+		if (sdata->type == IEEE80211_IF_TYPE_STA) {
 			if (0 /* FIX: more than one STA per AP */)
 				try_hwaccel = 0;
 		} else
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_AP ||
+		if (sdata->type != IEEE80211_IF_TYPE_AP ||
 		    dev != local->wdev)
 			try_hwaccel = 0;
 	} else {
@@ -541,8 +541,8 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 	 * optimized by using non-default keys (at least with Atheros ar521x).
 	 */
 	if (!sta && alg == ALG_WEP && !local->default_wep_only &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_AP) {
+	    sdata->type != IEEE80211_IF_TYPE_IBSS &&
+	    sdata->type != IEEE80211_IF_TYPE_AP) {
 		try_hwaccel = 0;
 	}
 
@@ -559,7 +559,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		 */
 			try_hwaccel = 0;
 		}
-		else if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+		else if (sdata->type == IEEE80211_IF_TYPE_STA) {
 			sta = sta_info_get(local, sdata->u.sta.bssid);
 			if (sta) {
 				if (sta->flags & WLAN_STA_WME) {
@@ -1014,7 +1014,7 @@ static int ieee80211_ioctl_update_if(str
 			}
 		}
 
-		if (wds_dev == NULL || sdata->type != IEEE80211_SUB_IF_TYPE_WDS)
+		if (wds_dev == NULL || sdata->type != IEEE80211_IF_TYPE_WDS)
 			return -ENODEV;
 
 		return ieee80211_if_update_wds(wds_dev, wds->remote_addr);
@@ -1052,8 +1052,8 @@ static int ieee80211_ioctl_sta_get_state
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
 		return -EINVAL;
 	param->u.sta_get_state.state = sdata->u.sta.state;
 	return 0;
@@ -1066,8 +1066,8 @@ static int ieee80211_ioctl_mlme(struct n
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
 		return -EINVAL;
 	switch (param->u.mlme.cmd) {
 	case MLME_STA_DEAUTH:
@@ -1126,8 +1126,8 @@ static int ieee80211_set_gen_ie(struct n
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS)
 		return ieee80211_sta_set_extra_ie(dev, ie, len);
 
 	kfree(local->conf.generic_elem);
@@ -1671,7 +1671,7 @@ #if 0
 			IEEE80211_DEV_TO_SUB_IF(dev);
 		sta_info_flush(local, NULL);
 		if (local->conf.mode == IW_MODE_ADHOC &&
-		    sdata->type == IEEE80211_SUB_IF_TYPE_STA) {
+		    sdata->type == IEEE80211_IF_TYPE_STA) {
 			/* Clear drop_unencrypted when leaving adhoc mode since
 			 * only adhoc mode is using automatic setting for this
 			 * in 80211.o. */
@@ -1699,22 +1699,22 @@ static int ieee80211_ioctl_giwmode(struc
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	switch (sdata->type) {
-	case IEEE80211_SUB_IF_TYPE_AP:
+	case IEEE80211_IF_TYPE_AP:
 		*mode = IW_MODE_MASTER;
 		break;
-	case IEEE80211_SUB_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_STA:
 		*mode = IW_MODE_INFRA;
 		break;
-	case IEEE80211_SUB_IF_TYPE_IBSS:
+	case IEEE80211_IF_TYPE_IBSS:
 		*mode = IW_MODE_ADHOC;
 		break;
-	case IEEE80211_SUB_IF_TYPE_MNTR:
+	case IEEE80211_IF_TYPE_MNTR:
 		*mode = IW_MODE_MONITOR;
 		break;
-	case IEEE80211_SUB_IF_TYPE_WDS:
+	case IEEE80211_IF_TYPE_WDS:
 		*mode = IW_MODE_REPEAT;
 		break;
-	case IEEE80211_SUB_IF_TYPE_VLAN:
+	case IEEE80211_IF_TYPE_VLAN:
 		*mode = IW_MODE_SECOND;		/* FIXME */
 		break;
 	default:
@@ -1807,8 +1807,8 @@ static int ieee80211_ioctl_siwessid(stru
 		len--;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS)
 		return ieee80211_sta_set_ssid(dev, ssid, len);
 
 	kfree(local->conf.ssid);
@@ -1831,8 +1831,8 @@ static int ieee80211_ioctl_giwessid(stru
 
 	struct ieee80211_sub_if_data *sdata;
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		int res = ieee80211_sta_get_ssid(dev, ssid, &len);
 		if (res == 0)
 			data->length = len;
@@ -1856,8 +1856,8 @@ static int ieee80211_ioctl_siwap(struct 
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		int changed_bssid = 0;
 		if (memcmp(local->conf.client_bssid, (u8 *) &ap_addr->sa_data,
 			   ETH_ALEN) != 0)
@@ -1869,7 +1869,7 @@ static int ieee80211_ioctl_siwap(struct 
 			       "the low-level driver\n", dev->name);
 		}
 		return ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
-	} else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) {
+	} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 		if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
 			   ETH_ALEN) == 0)
 			return 0;
@@ -1887,12 +1887,12 @@ static int ieee80211_ioctl_giwap(struct 
         struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		ap_addr->sa_family = ARPHRD_ETHER;
 		memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
 		return 0;
-	} else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) {
+	} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 		ap_addr->sa_family = ARPHRD_ETHER;
 		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
 		return 0;
@@ -2163,7 +2163,7 @@ ieee80211_ioctl_force_unicast_rate(struc
 	struct ieee80211_local *local = dev->priv;
 	int i;
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_AP)
+	if (sdata->type != IEEE80211_IF_TYPE_AP)
 		return -ENOENT;
 
 	if (rate == 0) {
@@ -2189,7 +2189,7 @@ ieee80211_ioctl_max_ratectrl_rate(struct
 	struct ieee80211_local *local = dev->priv;
 	int i;
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_AP)
+	if (sdata->type != IEEE80211_IF_TYPE_AP)
 		return -ENOENT;
 
 	if (rate == 0) {
@@ -2306,8 +2306,8 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_AP_AUTH_ALGS:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS) {
 			sdata->u.sta.auth_algs = value;
 		} else
 			ret = -EOPNOTSUPP;
@@ -2316,7 +2316,7 @@ static int ieee80211_ioctl_prism2_param(
 	case PRISM2_PARAM_DTIM_PERIOD:
 		if (value < 1)
 			ret = -EINVAL;
-		else if (sdata->type != IEEE80211_SUB_IF_TYPE_AP)
+		else if (sdata->type != IEEE80211_IF_TYPE_AP)
 			ret = -ENOENT;
 		else
 			sdata->u.ap.dtim_period = value;
@@ -2483,15 +2483,15 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_MIXED_CELL:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.mixed_cell = !!value;
 		break;
 
 	case PRISM2_PARAM_KEY_MGMT:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.key_mgmt = value;
@@ -2502,14 +2502,14 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_CREATE_IBSS:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.create_ibss = !!value;
 		break;
 	case PRISM2_PARAM_WMM_ENABLED:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			sdata->u.sta.wmm_enabled = !!value;
@@ -2550,15 +2550,15 @@ static int ieee80211_ioctl_get_prism2_pa
 		break;
 
 	case PRISM2_PARAM_AP_AUTH_ALGS:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS) {
 			*param = sdata->u.sta.auth_algs;
 		} else
 			ret = -EOPNOTSUPP;
 		break;
 
 	case PRISM2_PARAM_DTIM_PERIOD:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_AP)
+		if (sdata->type != IEEE80211_IF_TYPE_AP)
 			ret = -ENOENT;
 		else
 			*param = sdata->u.ap.dtim_period;
@@ -2675,29 +2675,29 @@ static int ieee80211_ioctl_get_prism2_pa
 		break;
 
 	case PRISM2_PARAM_CREATE_IBSS:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			*param = !!sdata->u.sta.create_ibss;
 		break;
 
 	case PRISM2_PARAM_MIXED_CELL:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			*param = !!sdata->u.sta.mixed_cell;
 		break;
 
 	case PRISM2_PARAM_KEY_MGMT:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
 			ret = -EINVAL;
 		else
 			*param = sdata->u.sta.key_mgmt;
 		break;
 	case PRISM2_PARAM_WMM_ENABLED:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
 			*param = !!sdata->u.sta.wmm_enabled;
@@ -2739,8 +2739,8 @@ static int ieee80211_ioctl_siwmlme(struc
 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA ||
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+	if (sdata->type != IEEE80211_IF_TYPE_STA ||
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
 		return -EINVAL;
 
 	switch (mlme->cmd) {
@@ -2861,7 +2861,7 @@ static int ieee80211_ioctl_siwauth(struc
 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
 		break;
 	case IW_AUTH_KEY_MGMT:
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
 			ret = -EINVAL;
 		else {
 			/*
@@ -2884,8 +2884,8 @@ static int ieee80211_ioctl_siwauth(struc
 		}
 		break;
 	case IW_AUTH_80211_AUTH_ALG:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS)
 			sdata->u.sta.auth_algs = data->value;
 		else
 			ret = -EOPNOTSUPP;
@@ -2911,8 +2911,8 @@ static int ieee80211_ioctl_giwauth(struc
 
 	switch (data->flags & IW_AUTH_INDEX) {
 	case IW_AUTH_80211_AUTH_ALG:
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_STA ||
-		    sdata->type == IEEE80211_SUB_IF_TYPE_IBSS)
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS)
 			data->value = sdata->u.sta.auth_algs;
 		else
 			ret = -EOPNOTSUPP;
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index 3709494..098599a 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -166,22 +166,22 @@ static char * ieee80211_proc_sub_if(char
 		p += sprintf(p, "bss=%p\n", sdata->bss);
 
 	switch (sdata->type) {
-	case IEEE80211_SUB_IF_TYPE_AP:
+	case IEEE80211_IF_TYPE_AP:
 		p = ieee80211_proc_sub_if_ap(p, &sdata->u.ap);
 		break;
-	case IEEE80211_SUB_IF_TYPE_WDS:
+	case IEEE80211_IF_TYPE_WDS:
 		p += sprintf(p, "type=wds\n");
 		p += sprintf(p, "wds.peer=" MACSTR "\n",
 			     MAC2STR(sdata->u.wds.remote_addr));
 		break;
-	case IEEE80211_SUB_IF_TYPE_VLAN:
+	case IEEE80211_IF_TYPE_VLAN:
 		p += sprintf(p, "type=vlan\n");
 		p += sprintf(p, "vlan.id=%d\n", sdata->u.vlan.id);
 		break;
-	case IEEE80211_SUB_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_STA:
 		p = ieee80211_proc_sub_if_sta(p, 0, &sdata->u.sta);
 		break;
-	case IEEE80211_SUB_IF_TYPE_IBSS:
+	case IEEE80211_IF_TYPE_IBSS:
 		p = ieee80211_proc_sub_if_sta(p, 1, &sdata->u.sta);
 		break;
 	}
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 5df6734..49c1b62 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -372,7 +372,7 @@ static void ieee80211_set_associated(str
 	if (assoc) {
 		struct ieee80211_sub_if_data *sdata;
 		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-		if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
 			return;
 		ifsta->prev_bssid_set = 1;
 		memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -863,7 +863,7 @@ static void ieee80211_rx_mgmt_auth(struc
 	u16 auth_alg, auth_transaction, status_code;
 
 	if (ifsta->state != IEEE80211_AUTHENTICATE &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS) {
+	    sdata->type != IEEE80211_IF_TYPE_IBSS) {
 		printk(KERN_DEBUG "%s: authentication frame received from "
 		       MACSTR ", but not in authenticate state - ignored\n",
 		       dev->name, MAC2STR(mgmt->sa));
@@ -877,7 +877,7 @@ static void ieee80211_rx_mgmt_auth(struc
 		return;
 	}
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
+	if (sdata->type != IEEE80211_IF_TYPE_IBSS &&
 	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
 		printk(KERN_DEBUG "%s: authentication frame received from "
 		       "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - "
@@ -886,7 +886,7 @@ static void ieee80211_rx_mgmt_auth(struc
 		return;
 	}
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS &&
+	if (sdata->type != IEEE80211_IF_TYPE_IBSS &&
 	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
 		printk(KERN_DEBUG "%s: authentication frame received from "
 		       "unknown BSSID (SA=" MACSTR " BSSID=" MACSTR ") - "
@@ -904,7 +904,7 @@ static void ieee80211_rx_mgmt_auth(struc
 	       dev->name, MAC2STR(mgmt->sa), auth_alg,
 	       auth_transaction, status_code);
 
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
 		/* IEEE 802.11 standard does not require authentication in IBSS
 		 * networks and most implementations do not seem to use it.
 		 * However, try to reply to authentication attempts if someone
@@ -1364,7 +1364,7 @@ #endif
 		((u64) pos[3] << 24) | ((u64) pos[2] << 16) |
 		((u64) pos[1] << 8) | ((u64) pos[0]);
 
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && beacon &&
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS && beacon &&
 	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
 #ifdef IEEE80211_IBSS_DEBUG
 		static unsigned long last_tsf_debug = 0;
@@ -1388,7 +1388,7 @@ #endif /* IEEE80211_IBSS_DEBUG */
 				   &elems) == ParseFailed)
 		invalid = 1;
 
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && elems.supp_rates &&
+	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_rate *rates;
@@ -1596,7 +1596,7 @@ static void ieee80211_rx_mgmt_beacon(str
 	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
 		return;
 	ifsta = &sdata->u.sta;
 
@@ -1651,7 +1651,7 @@ static void ieee80211_rx_mgmt_probe_req(
 	struct ieee80211_mgmt *resp;
 	u8 *pos, *end;
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_IBSS ||
+	if (sdata->type != IEEE80211_IF_TYPE_IBSS ||
 	    ifsta->state != IEEE80211_IBSS_JOINED ||
 	    len < 24 + 2 || ifsta->probe_resp == NULL)
 		return;
@@ -1720,7 +1720,7 @@ void ieee80211_sta_rx_mgmt(struct net_de
 		goto fail;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) {
+	if (sdata->type != IEEE80211_IF_TYPE_STA) {
 		printk(KERN_DEBUG "%s: ieee80211_sta_rx_mgmt: non-STA "
 		       "interface (type=%d)\n", dev->name, sdata->type);
 		goto fail;
@@ -1865,8 +1865,8 @@ void ieee80211_sta_timer(unsigned long p
 
 	dev = (struct net_device *) ptr;
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS) {
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS) {
 		printk(KERN_DEBUG "%s: ieee80211_sta_timer: non-STA interface "
 		       "(type=%d)\n", dev->name, sdata->type);
 		return;
@@ -1913,7 +1913,7 @@ static void ieee80211_sta_new_auth(struc
 	struct ieee80211_local *local = dev->priv;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
 		return;
 
 	if (local->hw->reset_tsf) {
@@ -2318,7 +2318,7 @@ int ieee80211_sta_set_ssid(struct net_de
 	ifsta->ssid_len = len;
 
 	ifsta->ssid_set = 1;
-	if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS && !ifsta->bssid_set) {
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS && !ifsta->bssid_set) {
 		ifsta->ibss_join_req = jiffies;
 		ifsta->state = IEEE80211_IBSS_SEARCH;
 		return ieee80211_sta_find_ibss(dev, ifsta);
@@ -2439,7 +2439,7 @@ static void ieee80211_sta_scan_timer(uns
 			local->last_scan_completed = jiffies;
 			memset(&wrqu, 0, sizeof(wrqu));
 			wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
-			if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) {
+			if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
 				struct ieee80211_sub_if_data *sdata =
 					IEEE80211_DEV_TO_SUB_IF(dev);
 				struct ieee80211_if_sta *ifsta = &sdata->u.sta;
@@ -2453,7 +2453,7 @@ static void ieee80211_sta_scan_timer(uns
 		skip = !(local->hw_modes & (1 << mode->mode));
 		chan = &mode->channels[local->scan_channel_idx];
 		if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
-		    (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS &&
+		    (sdata->type == IEEE80211_IF_TYPE_IBSS &&
 		     !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
 		    (local->hw_modes & (1 << MODE_IEEE80211G) &&
 		     mode->mode == MODE_IEEE80211B && local->scan_skip_11b))
@@ -2799,7 +2799,7 @@ struct sta_info * ieee80211_ibss_add_sta
 	spin_lock_bh(&local->sub_if_lock);
 	list_for_each(ptr, &local->sub_if_list) {
 		sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type == IEEE80211_SUB_IF_TYPE_IBSS &&
+		if (sdata->type == IEEE80211_IF_TYPE_IBSS &&
 		    memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
 			sta_dev = sdata->dev;
 			break;
@@ -2835,8 +2835,8 @@ int ieee80211_sta_deauthenticate(struct 
 	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
 	       dev->name, reason);
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA &&
-	    sdata->type != IEEE80211_SUB_IF_TYPE_IBSS)
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
 		return -EINVAL;
 
 	ieee80211_send_deauth(dev, ifsta, reason);
@@ -2853,7 +2853,7 @@ int ieee80211_sta_disassociate(struct ne
 	printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
 	       dev->name, reason);
 
-	if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
 		return -EINVAL;
 
 	if (!ifsta->associated)
diff --git a/net/d80211/wme.c b/net/d80211/wme.c
index 21689ed..51a197a 100644
--- a/net/d80211/wme.c
+++ b/net/d80211/wme.c
@@ -190,7 +190,7 @@ static inline int classify80211(struct s
 		return IEEE80211_TX_QUEUE_DATA0;
 	}
 
-	if (unlikely(pkt_data->sdata->type == IEEE80211_SUB_IF_TYPE_MGMT)) {
+	if (unlikely(pkt_data->sdata->type == IEEE80211_IF_TYPE_MGMT)) {
 		/* Data frames from hostapd (mainly, EAPOL) use AC_VO
 		* and they will include QoS control fields if
 		* the target STA is using WME. */
-- 
1.3.0


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

* [PATCH 8/17] d80211: ask driver for allowed iface combinations
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (6 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 7/17] d80211: rename IEEE80211_SUB_IF_TYPE_ constants Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 9/17] d80211: remove obsolete stuff Jiri Benc
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Not all combinations of interfaces (in fact, very few combination of
interfaces) are possible to be UP together. When an interface is going UP,
let's ask the driver if this is possible.

Please note that ieee80211_if_init_conf structure is not complete yet - new
fields will need to be added to allow drivers to decide.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h     |   52 ++++++++++++++++++++++++++++++++++++++++++++++
 net/d80211/ieee80211.c   |   30 ++++++++++++++++++++++-----
 net/d80211/ieee80211_i.h |    8 -------
 3 files changed, 77 insertions(+), 13 deletions(-)

77fe239e18433d16747c0851a5ecba6abe76820b
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 75e8e24..44417fc 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -305,6 +305,42 @@ struct ieee80211_conf {
 	u8 pulse_inband_threshold;
 };
 
+/**
+ * enum ieee80211_if_types - types of 802.11 network interface
+ * @IEEE80211_IF_TYPE_AP: interface in AP mode.
+ * @IEEE80211_IF_TYPE_MGMT: special interface for communication with hostap
+ *	daemon. Drivers should never see this type.
+ * @IEEE80211_IF_TYPE_STA: interface in STA (client) mode.
+ * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode.
+ * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode.
+ * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
+ * @IEEE80211_IF_TYPE_VLAN: not used.
+ */
+enum ieee80211_if_types {
+	IEEE80211_IF_TYPE_AP = 0x00000000,
+	IEEE80211_IF_TYPE_MGMT = 0x00000001,
+	IEEE80211_IF_TYPE_STA = 0x00000002,
+	IEEE80211_IF_TYPE_IBSS = 0x00000003,
+	IEEE80211_IF_TYPE_MNTR = 0x00000004,
+	IEEE80211_IF_TYPE_WDS = 0x5A580211,
+	IEEE80211_IF_TYPE_VLAN = 0x00080211,
+};
+
+/**
+ * struct ieee80211_if_init_conf - initial configuration of an interface
+ * @type: one of &enum ieee80211_if_types constants. Determines the type of
+ *	added/removed interface.
+ * @mac_addr: pointer to MAC address of the interface. This pointer is valid
+ *	until the interface is removed (i.e. it cannot be used after
+ *	remove_interface() callback was called for this interface).
+ *
+ * This structure is used in add_interface() and remove_interface()
+ * callbacks of &struct ieee80211_hw.
+ */
+struct ieee80211_if_init_conf {
+	int type;
+	void *mac_addr;
+};
 
 typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
 ieee80211_key_alg;
@@ -452,6 +488,22 @@ struct ieee80211_hw {
 	 * interrupts and beacon sending. */
 	int (*stop)(struct net_device *dev);
 
+	/* Handler for asking a driver if a new interface can be added (or,
+	 * more exactly, set UP). If the handler returns zero, the interface
+	 * is added. Driver should perform any initialization it needs prior
+	 * to returning zero. By returning non-zero, adding of the interface
+	 * is not permitted. The open() handler is called after
+	 * add_interface() if this is the first device added. At least one
+	 * of open() and add_interface() handler has to be non-NULL. If
+	 * add_interface() is NULL, one STA interface is permitted only. */
+	int (*add_interface)(struct net_device *dev,
+			     struct ieee80211_if_init_conf *conf);
+
+	/* Notify a driver that interface is going down. The stop() handler
+	 * is called prior to this if this is a last interface. */
+	void (*remove_interface)(struct net_device *dev,
+				 struct ieee80211_if_init_conf *conf);
+
 	/* Handler for configuration requests. IEEE 802.11 code calls this
 	 * function to change hardware configuration, e.g., channel. */
 	int (*config)(struct net_device *dev, struct ieee80211_conf *conf);
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index fae9d64..271c4d9 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1828,11 +1828,22 @@ static int ieee80211_open(struct net_dev
 	int res;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (local->hw->add_interface) {
+		struct ieee80211_if_init_conf conf;
 
-        if (local->open_count == 0) {
-		res = local->hw->open(sdata->master);
+		conf.type = sdata->type;
+		conf.mac_addr = dev->dev_addr;
+		res = local->hw->add_interface(sdata->master, &conf);
 		if (res)
 			return res;
+	}
+
+        if (local->open_count == 0) {
+		if (local->hw->open) {
+			res = local->hw->open(sdata->master);
+			if (res)
+				return res;
+		}
 		ieee80211_init_scan(sdata->master);
 	}
         local->open_count++;
@@ -1855,10 +1866,19 @@ static int ieee80211_stop(struct net_dev
 	local->open_count--;
         if (local->open_count == 0) {
 		ieee80211_stop_scan(sdata->master);
-		res = local->hw->stop(sdata->master);
-		if (res)
-			return res;
+		if (local->hw->stop) {
+			res = local->hw->stop(sdata->master);
+			if (res)
+				return res;
+		}
         }
+	if (local->hw->remove_interface) {
+		struct ieee80211_if_init_conf conf;
+
+		conf.type = sdata->type;
+		conf.mac_addr = dev->dev_addr;
+		local->hw->remove_interface(sdata->master, &conf);
+	}
 
 	return 0;
 }
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 9d18c71..d42b6fe 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -256,14 +256,6 @@ #define IEEE80211_AUTH_ALG_LEAP BIT(2)
 };
 
 
-#define IEEE80211_IF_TYPE_AP   0x00000000
-#define IEEE80211_IF_TYPE_MGMT 0x00000001
-#define IEEE80211_IF_TYPE_STA  0x00000002
-#define IEEE80211_IF_TYPE_IBSS 0x00000003
-#define IEEE80211_IF_TYPE_MNTR 0x00000004
-#define IEEE80211_IF_TYPE_WDS  0x5A580211
-#define IEEE80211_IF_TYPE_VLAN 0x00080211
-
 struct ieee80211_sub_if_data {
         struct list_head list;
         unsigned int type;
-- 
1.3.0


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

* [PATCH 9/17] d80211: remove obsolete stuff
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (7 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 8/17] d80211: ask driver for allowed iface combinations Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 10/17] d80211: fix interface configuration Jiri Benc
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Because any number of interfaces may be added, bss_devs and sta_devs arrays
cannot be fixed-size arrays. We can make them linked lists, but they are
needed for optimalization only (and even that is questionable with
subsequent patches). Let's remove them; we will probably want something
similar later to speed up packet receiving, but let's not bother ourselves
now.

Also, ieee80211_addr_inc is removed. Choosing of MAC address of a new STA
should be matter of userspace. It's responsibility of the stack not to allow
two STAs with the same MAC address to be up - this feature is introduced in
one of subsequent patches.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |    3 -
 net/d80211/hostapd_ioctl.h   |    1 
 net/d80211/ieee80211.c       |  164 ++++--------------------------------------
 net/d80211/ieee80211_i.h     |    9 --
 net/d80211/ieee80211_ioctl.c |   70 ------------------
 net/d80211/ieee80211_proc.c  |   12 ---
 net/d80211/ieee80211_sysfs.c |   29 -------
 7 files changed, 16 insertions(+), 272 deletions(-)

3180a84e9351200900e932690feb613d1f799068
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 44417fc..5dff49a 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -277,9 +277,6 @@ struct ieee80211_conf {
         int antenna_def;
         int antenna_mode;
 
-	u8 bssid_mask[ETH_ALEN];	/* ff:ff:ff:ff:ff:ff = 1 BSSID */
-	int bss_count;
-
 	int atheros_super_ag_compression;
 	int atheros_super_ag_fast_frame;
 	int atheros_super_ag_burst;
diff --git a/net/d80211/hostapd_ioctl.h b/net/d80211/hostapd_ioctl.h
index 42c2bc5..028caf1 100644
--- a/net/d80211/hostapd_ioctl.h
+++ b/net/d80211/hostapd_ioctl.h
@@ -129,7 +129,6 @@ enum {
 	PRISM2_HOSTAPD_SET_CHANNEL_FLAG = 1012,
 	PRISM2_HOSTAPD_SET_REGULATORY_DOMAIN = 1013,
 	PRISM2_HOSTAPD_SET_TX_QUEUE_PARAMS = 1014,
-	PRISM2_HOSTAPD_SET_BSS = 1015,
 	PRISM2_HOSTAPD_GET_TX_STATS = 1016,
 	PRISM2_HOSTAPD_UPDATE_IF = 1017,
 	PRISM2_HOSTAPD_SCAN_REQ = 1019,
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 271c4d9..e3e155e 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1569,17 +1569,14 @@ struct sk_buff * ieee80211_beacon_get(st
 	u8 *b_head, *b_tail;
 	int bh_len, bt_len;
 
-	spin_lock_bh(&local->sub_if_lock);
-	if (bss_idx < 0 || bss_idx >= local->bss_dev_count)
-		bdev = NULL;
-	else {
-		bdev = local->bss_devs[bss_idx];
+	bdev = dev_get_by_index(bss_idx);
+	if (bdev) {
 		sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
 		ap = &sdata->u.ap;
+		dev_put(bdev);
 	}
-	spin_unlock_bh(&local->sub_if_lock);
 
-	if (bdev == NULL || ap == NULL || ap->beacon_head == NULL) {
+	if (ap == NULL || ap->beacon_head == NULL) {
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "no beacon data avail for idx=%d "
@@ -1646,19 +1643,15 @@ ieee80211_get_buffered_bc(struct net_dev
 	ieee80211_txrx_result res = TXRX_DROP;
 	struct net_device *bdev;
 	struct ieee80211_sub_if_data *sdata;
-	struct ieee80211_if_ap *bss;
+	struct ieee80211_if_ap *bss = NULL;
 
-	spin_lock_bh(&local->sub_if_lock);
-	if (bss_idx < 0 || bss_idx >= local->bss_dev_count) {
-		bdev = NULL;
-		bss = NULL;
-	} else {
-		bdev = local->bss_devs[bss_idx];
+	bdev = dev_get_by_index(bss_idx);
+	if (bdev) {
 		sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
 		bss = &sdata->u.ap;
+		dev_put(bdev);
 	}
-	spin_unlock_bh(&local->sub_if_lock);
-	if (bdev == NULL || bss == NULL || bss->beacon_head == NULL)
+	if (bss == NULL || bss->beacon_head == NULL)
 		return NULL;
 
 	if (bss->dtim_count != 0)
@@ -1911,14 +1904,14 @@ ieee80211_get_wds_dev(struct ieee80211_l
 static struct net_device * ieee80211_own_bssid(struct ieee80211_local *local,
 					       u8 *addr)
 {
-	int i;
 	struct net_device *dev = NULL;
+	struct ieee80211_sub_if_data *sdata;
 
 	spin_lock_bh(&local->sub_if_lock);
-	for (i = 0; i < local->bss_dev_count; i++) {
-		if ((memcmp(local->bss_devs[i]->dev_addr, addr, ETH_ALEN) == 0)
-		) {
-			dev = local->bss_devs[i];
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		if (sdata->type == IEEE80211_IF_TYPE_AP &&
+		    memcmp(addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
+			dev = sdata->dev;
 			break;
 		}
 	}
@@ -1934,31 +1927,9 @@ static struct net_device * ieee80211_sta
 {
 	struct list_head *ptr;
 	int multicast;
-	u8 *own_addr = local->mdev->dev_addr;
 
 	multicast = a1[0] & 0x01;
 
-	/* Try O(1) lookup for a common case of only one AP being used. */
-	if (own_addr[0] == a1[0] && own_addr[1] == a1[1] &&
-	    own_addr[2] == a1[2]) {
-		int index = (((int) a1[3] << 16) | ((int) a1[4] << 8) | a1[5])
-			- (((int) own_addr[3] << 16) |
-			   ((int) own_addr[4] << 8) | own_addr[5]);
-		if (index >= 0 && index < local->conf.bss_count &&
-		    local->sta_devs[index]) {
-			struct net_device *dev = local->sta_devs[index];
-			struct ieee80211_sub_if_data *sdata;
-			sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-			if (memcmp(addr, sdata->u.sta.bssid, ETH_ALEN) == 0) {
-				*sta_multicast = multicast;
-				return dev;
-			}
-		}
-	}
-
-	if (!multicast)
-		return NULL;
-
 	/* Could not find station interface, resort to O(n) lookup. */
 	list_for_each(ptr, &local->sub_if_list) {
 		struct ieee80211_sub_if_data *sdata =
@@ -1982,27 +1953,6 @@ static struct net_device * ieee80211_sta
 }
 
 
-static int ieee80211_own_addr(struct net_device *dev, u8 *addr)
-{
-	struct ieee80211_local *local = dev->priv;
-	u8 *own = dev->dev_addr;
-	int index;
-
-	/* Optimization: assume that BSSID mask does not change for first
-	 * three octets. */
-	if (own[0] != addr[0] || own[1] != addr[1] || own[2] != addr[2])
-		return 0;
-
-	index = (((int) addr[3] << 16) | ((int) addr[4] << 8) | addr[5]) -
-		(((int) own[3] << 16) | ((int) own[4] << 8) | own[5]);
-	if (index >= 0 && index < local->conf.bss_count &&
-	    local->sta_devs[index])
-		return 1;
-
-	return 0;
-}
-
-
 static ieee80211_txrx_result
 ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
 {
@@ -2719,7 +2669,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
 	 * FIX: Filter out multicast to foreign BSSID. */
 	if (rx->sdata->type == IEEE80211_IF_TYPE_STA &&
 	    !MULTICAST_ADDR(hdr->addr1) &&
-	    !ieee80211_own_addr(rx->dev, hdr->addr1))
+	    memcmp(rx->dev->dev_addr, hdr->addr1, ETH_ALEN) != 0)
 		return TXRX_DROP;
 
 	/* Drop disallowed frame classes based on STA auth/assoc state;
@@ -4023,13 +3973,9 @@ static void ieee80211_if_ap_init(struct 
 int ieee80211_if_add_ap(struct net_device *dev, const char *name, u8 *bssid,
 			  int locked)
 {
-        struct ieee80211_local *local = dev->priv;
 	struct net_device *ap_dev = NULL;
         struct ieee80211_sub_if_data *sdata = NULL;
 
-	if (local->bss_dev_count >= local->conf.bss_count)
-		return -ENOBUFS;
-
         if (strlen(name) != 0) {
 		ap_dev = dev_get_by_name(name);
 		if (ap_dev) {
@@ -4046,37 +3992,16 @@ int ieee80211_if_add_ap(struct net_devic
 	sdata = IEEE80211_DEV_TO_SUB_IF(ap_dev);
 	ieee80211_if_ap_init(sdata);
 	ieee80211_proc_init_virtual(ap_dev);
-	spin_lock_bh(&local->sub_if_lock);
-	local->bss_devs[local->bss_dev_count] = ap_dev;
-	local->bss_dev_count++;
-	spin_unlock_bh(&local->sub_if_lock);
 
         return 0;
 }
 
 
-static void ieee80211_addr_inc(u8 *addr)
-{
-	int pos = 5;
-	while (pos >= 0) {
-		addr[pos]++;
-		if (addr[pos] != 0)
-			break;
-		pos--;
-	}
-}
-
-
 int ieee80211_if_add_sta(struct net_device *dev, const char *name, int locked)
 {
-	struct ieee80211_local *local = dev->priv;
 	struct net_device *sta_dev;
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_sta *ifsta;
-	int i;
-
-	if (local->sta_dev_count >= local->conf.bss_count)
-		return -ENOBUFS;
 
 	if (strlen(name) != 0) {
 		sta_dev = dev_get_by_name(name);
@@ -4095,24 +4020,6 @@ int ieee80211_if_add_sta(struct net_devi
 	sdata->type = IEEE80211_IF_TYPE_STA;
 	ieee80211_proc_init_virtual(sta_dev);
 
-	spin_lock_bh(&local->sub_if_lock);
-	for (i = 0; i < local->conf.bss_count; i++) {
-		if (local->sta_devs[i] == NULL) {
-			local->sta_devs[i] = sta_dev;
-			local->sta_dev_count++;
-			printk(KERN_DEBUG "%s: using STA entry %d\n",
-			       sta_dev->name, i);
-			while (i > 0) {
-				ieee80211_addr_inc(sta_dev->dev_addr);
-				i--;
-			}
-			printk(KERN_DEBUG "%s: MAC address " MACSTR "\n",
-			       sta_dev->name, MAC2STR(sta_dev->dev_addr));
-			break;
-		}
-	}
-	spin_unlock_bh(&local->sub_if_lock);
-
 	init_timer(&ifsta->timer);
 	ifsta->timer.data = (unsigned long) sta_dev;
 	ifsta->timer.function = ieee80211_sta_timer;
@@ -4132,7 +4039,7 @@ static void ieee80211_if_del(struct ieee
 {
         struct sta_info *sta;
 	u8 addr[ETH_ALEN];
-	int i, j;
+	int i;
         struct list_head *ptr, *n;
 
 	memset(addr, 0xff, ETH_ALEN);
@@ -4170,23 +4077,6 @@ #endif
 
 		kfree(sdata->u.ap.beacon_head);
 		kfree(sdata->u.ap.beacon_tail);
-		spin_lock_bh(&local->sub_if_lock);
-		for (j = 0; j < local->bss_dev_count; j++) {
-			if (sdata->dev == local->bss_devs[j]) {
-				if (j + 1 < local->bss_dev_count) {
-					memcpy(&local->bss_devs[j],
-					       &local->bss_devs[j + 1],
-					       (local->bss_dev_count - j - 1) *
-					       sizeof(local->bss_devs[0]));
-					local->bss_devs[local->bss_dev_count -
-							1] = NULL;
-				} else
-					local->bss_devs[j] = NULL;
-				local->bss_dev_count--;
-				break;
-			}
-		}
-		spin_unlock_bh(&local->sub_if_lock);
 
 		if (sdata->dev != local->mdev) {
 			struct sk_buff *skb;
@@ -4223,13 +4113,6 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 			dev_kfree_skb(sdata->u.sta.probe_resp);
 			sdata->u.sta.probe_resp = NULL;
 		}
-		for (i = 0; i < local->conf.bss_count; i++) {
-			if (local->sta_devs[i] == sdata->dev) {
-				local->sta_devs[i] = NULL;
-				local->sta_dev_count--;
-				break;
-			}
-		}
 
 		break;
 	}
@@ -4428,17 +4311,6 @@ struct net_device *ieee80211_alloc_hw(si
 	local->conf.calib_int = 60;
 	local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
 	local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
-	local->conf.bss_count = 1;
-	memset(local->conf.bssid_mask, 0xff, ETH_ALEN);
-	local->bss_devs = kmalloc(sizeof(struct net_device *), GFP_KERNEL);
-	if (local->bss_devs == NULL)
-		goto fail;
-	local->bss_devs[0] = local->wdev;
-	local->bss_dev_count = 1;
-	local->sta_devs = kmalloc(sizeof(struct net_device *), GFP_KERNEL);
-	if (local->sta_devs == NULL)
-		goto fail;
-	local->sta_devs[0] = NULL;
 
         local->scan.in_scan = 0;
 	local->hw_modes = (unsigned int) -1;
@@ -4694,10 +4566,6 @@ void ieee80211_unregister_hw(struct net_
 
 void ieee80211_free_hw(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
-
-	kfree(local->sta_devs);
-	kfree(local->bss_devs);
 	kfree(dev);
 }
 
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index d42b6fe..3766232 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -372,13 +372,6 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 
         spinlock_t sub_if_lock; /* mutex for STA data structures */
         struct list_head sub_if_list;
-	struct net_device **bss_devs; /* pointer to IF_TYPE_AP devices for
-				       * quick access to BSS data */
-	int bss_dev_count; /* number of used entries in bss_devs; note: the
-			    * total size of bss_devs array is stored in
-			    * conf.bss_count */
-	struct net_device **sta_devs; /* pointer to IF_TYPE_STA devices */
-	int sta_dev_count; /* number of used entries in sta_devs */
 	int sta_scanning;
 	int scan_hw_mode_idx;
 	int scan_channel_idx;
@@ -553,8 +546,6 @@ int ieee80211_if_remove_sta(struct net_d
 /* ieee80211_ioctl.c */
 int ieee80211_set_compression(struct ieee80211_local *local,
 			      struct net_device *dev, struct sta_info *sta);
-int ieee80211_set_bss_count(struct net_device *dev, int new_count,
-			    u8 *bssid_mask);
 /* ieee80211_sta.c */
 void ieee80211_sta_timer(unsigned long ptr);
 void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 2fd910d..461e2d9 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1223,73 +1223,6 @@ static int ieee80211_ioctl_get_tx_stats(
 }
 
 
-int ieee80211_set_bss_count(struct net_device *dev, int new_count,
-			    u8 *bssid_mask)
-{
-	struct ieee80211_local *local = dev->priv;
-	struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev);
-	int i, bss_count;
-	struct net_device **bss_devs, **prev;
-	struct net_device **sta_devs, **prev_sta_devs;
-
-	bss_count = 0;
-	for (i = 0; i < conf->bss_count; i++) {
-		if (local->bss_devs[i])
-			bss_count++;
-	}
-
-	if (new_count < bss_count) {
-		printk(KERN_DEBUG "%s: invalid BSS count %d (in use: %d)\n",
-		       dev->name, new_count, bss_count);
-		return -EINVAL;
-	}
-
-	bss_devs = kmalloc(new_count * sizeof(struct net_device *),
-			   GFP_KERNEL);
-	if (bss_devs == NULL)
-		return -ENOMEM;
-	sta_devs = kmalloc(new_count * sizeof(struct net_device *),
-			   GFP_KERNEL);
-	if (sta_devs == NULL) {
-		kfree(bss_devs);
-		return -ENOMEM;
-	}
-
-	spin_lock_bh(&local->sub_if_lock);
-	memcpy(bss_devs, local->bss_devs,
-	       bss_count * sizeof(struct net_device *));
-	memset(&bss_devs[bss_count], 0,
-	       (new_count - bss_count) * sizeof(struct net_device *));
-
-	if (bssid_mask)
-		memcpy(conf->bssid_mask, bssid_mask, ETH_ALEN);
-
-	prev = local->bss_devs;
-	local->bss_devs = bss_devs;
-	conf->bss_count = new_count;
-
-	memcpy(sta_devs, local->sta_devs,
-	       bss_count * sizeof(struct net_device *));
-	memset(&sta_devs[bss_count], 0,
-	       (new_count - bss_count) * sizeof(struct net_device *));
-	prev_sta_devs = local->sta_devs;
-	local->sta_devs = sta_devs;
-
-	spin_unlock_bh(&local->sub_if_lock);
-	kfree(prev);
-	kfree(prev_sta_devs);
-
-	return ieee80211_hw_config(dev);
-}
-
-static int ieee80211_ioctl_set_bss(struct net_device *dev,
-				   struct prism2_hostapd_param *param)
-{
-	return ieee80211_set_bss_count(dev, param->u.set_bss.bss_count,
-				       param->u.set_bss.bssid_mask);
-}
-
-
 static int ieee80211_ioctl_set_channel_flag(struct net_device *dev,
 					    struct prism2_hostapd_param *param)
 {
@@ -1441,9 +1374,6 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */
 	case PRISM2_HOSTAPD_SET_TX_QUEUE_PARAMS:
 		ret = ieee80211_ioctl_set_tx_queue_params(dev, param);
 		break;
-	case PRISM2_HOSTAPD_SET_BSS:
-		ret = ieee80211_ioctl_set_bss(dev, param);
-		break;
 	case PRISM2_HOSTAPD_GET_TX_STATS:
 		ret = ieee80211_ioctl_get_tx_stats(dev, param);
 		break;
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index 098599a..a886280 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -374,7 +374,6 @@ static int ieee80211_proc_debug_read(cha
 {
 	char *p = page;
 	struct ieee80211_local *local = (struct ieee80211_local *) data;
-	int i;
 
 	if (off != 0) {
 		*eof = 1;
@@ -439,17 +438,6 @@ #endif /* CONFIG_D80211_DEBUG_COUNTERS *
 
 	p += sprintf(p, "num_scans=%u\n", local->scan.num_scans);
 
-	p += sprintf(p,
-		     "conf.bss_count=%d\n"
-		     "bss_dev_count=%u\n",
-		     local->conf.bss_count, local->bss_dev_count);
-	for (i = 0; i < local->conf.bss_count; i++) {
-		p += sprintf(p, "bss_dev[%d]=%p (%s)\n",
-			     i, local->bss_devs[i],
-			     (i < local->bss_dev_count && local->bss_devs[i]) ?
-			     local->bss_devs[i]->name : "N/A");
-	}
-
 	return (p - page);
 }
 
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 32fb380..082404f 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -51,33 +51,6 @@ static ssize_t store_remove_iface(struct
 	return res < 0 ? res : len;
 }
 
-static ssize_t show_max_iface_count(struct class_device *dev,
-				    char *buf)
-{
-	struct ieee80211_local *local = to_ieee80211_local(dev);
-
-	return sprintf(buf, "%d\n", local->conf.bss_count);
-}
-
-static ssize_t store_max_iface_count(struct class_device *dev,
-				     const char *buf, size_t len)
-{
-	struct ieee80211_local *local = to_ieee80211_local(dev);
-	unsigned long new_count;
-	char *endp;
-	int res;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-	new_count = simple_strtoul(buf, &endp, 0);
-	if (endp == buf)
-		return -EINVAL;
-	rtnl_lock();
-	res = ieee80211_set_bss_count(local->mdev, new_count, NULL);
-	rtnl_unlock();
-	return res < 0 ? res : len;
-}
-
 #ifdef CONFIG_HOTPLUG
 static int ieee80211_uevent(struct class_device *cd, char **envp,
 			    int num_envp, char *buf, int size)
@@ -98,8 +71,6 @@ #endif
 static struct class_device_attribute ieee80211_class_dev_attrs[] = {
 	__ATTR(add_iface, S_IWUSR, NULL, store_add_iface),
 	__ATTR(remove_iface, S_IWUSR, NULL, store_remove_iface),
-	__ATTR(max_iface_count, S_IRUGO | S_IWUSR,
-	       show_max_iface_count, store_max_iface_count),
 	{}
 };
 
-- 
1.3.0


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

* [PATCH 10/17] d80211: fix interface configuration
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (8 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 9/17] d80211: remove obsolete stuff Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 11/17] d80211: rename adm_status to radio_enabled Jiri Benc
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

This patch fixes some problems in interface configuration.

- Pass interface ID to add_interface and remove_interface callbacks. This ID
  is used by a driver when calling ieee80211_beacon_get and
  ieee80211_get_buffered_bc functions.
- New configuration callback, config_interface, is introduced.
- Allow BSSID to be set per-interface.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |   63 ++++++++++++++++++++++++++++++++++--------
 net/d80211/ieee80211.c       |   35 +++++++++++++++++++----
 net/d80211/ieee80211_i.h     |    1 +
 net/d80211/ieee80211_ioctl.c |   11 -------
 net/d80211/ieee80211_sta.c   |   15 +++++++++-
 5 files changed, 93 insertions(+), 32 deletions(-)

9b4d05977dda50bec721e696ec3cf98afd7d1ca9
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 5dff49a..84abd7c 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -286,8 +286,6 @@ struct ieee80211_conf {
 
 	int atheros_xr;
 
-	u8 client_bssid[ETH_ALEN];
-
 	/* Following five fields are used for IEEE 802.11H */
 	unsigned int radar_detect;
 	unsigned int spect_mgmt;
@@ -325,6 +323,9 @@ enum ieee80211_if_types {
 
 /**
  * struct ieee80211_if_init_conf - initial configuration of an interface
+ * @if_id: internal interface ID. This number has no particular meaning to
+ *	drivers and the only allowed usage is to pass it to
+ *	ieee80211_beacon_get() and ieee80211_get_buffered_bc() functions.
  * @type: one of &enum ieee80211_if_types constants. Determines the type of
  *	added/removed interface.
  * @mac_addr: pointer to MAC address of the interface. This pointer is valid
@@ -335,10 +336,27 @@ enum ieee80211_if_types {
  * callbacks of &struct ieee80211_hw.
  */
 struct ieee80211_if_init_conf {
+	int if_id;
 	int type;
 	void *mac_addr;
 };
 
+/**
+ * struct ieee80211_if_conf - configuration of an interface
+ * @type: type of the interface. This is always the same as was specified in
+ *	&struct ieee80211_if_init_conf. The type of interface never change
+ *	during the live of the interface; this field is present only for
+ *	convenience.
+ * @bssid: BSSID of the network we are associated to/creating.
+ *
+ * This structure is passed to config_interface() callback of
+ * &struct ieee80211_hw.
+ */
+struct ieee80211_if_conf {
+	int type;
+	u8 *bssid;
+};
+
 typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
 ieee80211_key_alg;
 
@@ -505,6 +523,11 @@ struct ieee80211_hw {
 	 * function to change hardware configuration, e.g., channel. */
 	int (*config)(struct net_device *dev, struct ieee80211_conf *conf);
 
+	/* Handler for configuration requests related to interfaces (e.g.
+	 * BSSID). */
+	int (*config_interface)(struct net_device *dev, int if_id,
+				struct ieee80211_if_conf *conf);
+
 	/* Set TIM bit handler. If the hardware/firmware takes care of beacon
 	 * generation, IEEE 802.11 code uses this function to tell the
 	 * low-level to set (or clear if set==0) TIM bit for the given aid. If
@@ -682,16 +705,31 @@ void ieee80211_tx_status(struct net_devi
 void ieee80211_tx_status_irqsafe(struct net_device *dev, struct sk_buff *skb,
 				 struct ieee80211_tx_status *status);
 
-/* Beacon generation function. If the beacon frames are generated by the host
- * system (i.e., not in hardware/firmware), the low-level driver uses this
- * function to receive the next beacon frame from the 802.11 code. The
- * low-level is responsible for calling this function before beacon data is
- * needed (e.g., based on hardware interrupt). Returned skb is used only once
- * and low-level driver is responsible of freeing it. */
-struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int bss_idx,
+/**
+ * ieee80211_beacon_get - beacon generation function
+ * @dev: pointer to &struct net_device as obtained from
+ *	ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send this beacon.
+ *
+ * If the beacon frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next beacon frame from the 802.11 code. The low-level is responsible
+ * for calling this function before beacon data is needed (e.g., based on
+ * hardware interrupt). Returned skb is used only once and low-level driver
+ * is responsible of freeing it.
+ */
+struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int if_id,
 				      struct ieee80211_tx_control *control);
 
-/* Function for accessing buffered broadcast and multicast frames. If
+/**
+ * ieee80211_beacon_get - accessing buffered broadcast and multicast frames
+ * @dev: pointer to &struct net_device as obtained from
+ *	ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send returned frame.
+ *
+ * Function for accessing buffered broadcast and multicast frames. If
  * hardware/firmware does not implement buffering of broadcast/multicast
  * frames when power saving is used, 802.11 code buffers them in the host
  * memory. The low-level driver uses this function to fetch next buffered
@@ -704,9 +742,10 @@ struct sk_buff * ieee80211_beacon_get(st
  * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns
  * NULL if the previous generated beacon was not DTIM, so the low-level driver
  * does not need to check for DTIM beacons separately and should be able to
- * use common code for all beacons. */
+ * use common code for all beacons.
+ */
 struct sk_buff *
-ieee80211_get_buffered_bc(struct net_device *dev, int bss_idx,
+ieee80211_get_buffered_bc(struct net_device *dev, int if_id,
 			  struct ieee80211_tx_control *control);
 
 /* Low level drivers that have their own MLME and MAC indicate
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e3e155e..e6d4342 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1556,7 +1556,7 @@ static void ieee80211_beacon_add_tim(str
 }
 
 
-struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int bss_idx,
+struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int if_id,
 				      struct ieee80211_tx_control *control)
 {
 	struct ieee80211_local *local = dev->priv;
@@ -1569,18 +1569,19 @@ struct sk_buff * ieee80211_beacon_get(st
 	u8 *b_head, *b_tail;
 	int bh_len, bt_len;
 
-	bdev = dev_get_by_index(bss_idx);
+	bdev = dev_get_by_index(if_id);
 	if (bdev) {
 		sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
 		ap = &sdata->u.ap;
 		dev_put(bdev);
 	}
 
-	if (ap == NULL || ap->beacon_head == NULL) {
+	if (ap == NULL || sdata->type != IEEE80211_IF_TYPE_AP ||
+	    ap->beacon_head == NULL) {
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "no beacon data avail for idx=%d "
-			       "(%s)\n", bss_idx, bdev ? bdev->name : "N/A");
+			       "(%s)\n", if_id, bdev ? bdev->name : "N/A");
 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		return NULL;
 	}
@@ -1632,7 +1633,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 
 struct sk_buff *
-ieee80211_get_buffered_bc(struct net_device *dev, int bss_idx,
+ieee80211_get_buffered_bc(struct net_device *dev, int if_id,
 			  struct ieee80211_tx_control *control)
 {
 	struct ieee80211_local *local = dev->priv;
@@ -1645,13 +1646,14 @@ ieee80211_get_buffered_bc(struct net_dev
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_ap *bss = NULL;
 
-	bdev = dev_get_by_index(bss_idx);
+	bdev = dev_get_by_index(if_id);
 	if (bdev) {
 		sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
 		bss = &sdata->u.ap;
 		dev_put(bdev);
 	}
-	if (bss == NULL || bss->beacon_head == NULL)
+	if (bss == NULL || sdata->type != IEEE80211_IF_TYPE_AP ||
+	    bss->beacon_head == NULL)
 		return NULL;
 
 	if (bss->dtim_count != 0)
@@ -1694,6 +1696,23 @@ ieee80211_get_buffered_bc(struct net_dev
 	return skb;
 }
 
+int ieee80211_if_config(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_if_conf conf;
+
+	if (!local->hw->config_interface)
+		return 0;
+
+	memset(&conf, 0, sizeof(conf));
+	conf.type = sdata->type;
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		conf.bssid = sdata->u.sta.bssid;
+	}
+	return local->hw->config_interface(local->mdev, dev->ifindex, &conf);
+}
 
 int ieee80211_hw_config(struct net_device *dev)
 {
@@ -1824,6 +1843,7 @@ static int ieee80211_open(struct net_dev
 	if (local->hw->add_interface) {
 		struct ieee80211_if_init_conf conf;
 
+		conf.if_id = dev->ifindex;
 		conf.type = sdata->type;
 		conf.mac_addr = dev->dev_addr;
 		res = local->hw->add_interface(sdata->master, &conf);
@@ -1868,6 +1888,7 @@ static int ieee80211_stop(struct net_dev
 	if (local->hw->remove_interface) {
 		struct ieee80211_if_init_conf conf;
 
+		conf.if_id = dev->ifindex;
 		conf.type = sdata->type;
 		conf.mac_addr = dev->dev_addr;
 		local->hw->remove_interface(sdata->master, &conf);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 3766232..8fd0ac4 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -484,6 +484,7 @@ #endif /* CONFIG_D80211_DEBUG_COUNTERS *
 
 /* ieee80211.c */
 int ieee80211_hw_config(struct net_device *dev);
+int ieee80211_if_config(struct net_device *dev);
 struct ieee80211_key_conf *
 ieee80211_key_data2conf(struct ieee80211_local *local,
 			struct ieee80211_key *data);
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 461e2d9..00efe47 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1782,22 +1782,11 @@ static int ieee80211_ioctl_siwap(struct 
 				 struct iw_request_info *info,
 				 struct sockaddr *ap_addr, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	if (sdata->type == IEEE80211_IF_TYPE_STA ||
 	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
-		int changed_bssid = 0;
-		if (memcmp(local->conf.client_bssid, (u8 *) &ap_addr->sa_data,
-			   ETH_ALEN) != 0)
-			changed_bssid = 1;
-		memcpy(local->conf.client_bssid, (u8 *) &ap_addr->sa_data,
-		       ETH_ALEN);
-		if (changed_bssid && ieee80211_hw_config(dev)) {
-			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
-			       "the low-level driver\n", dev->name);
-		}
 		return ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
 	} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
 		if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 49c1b62..d9c3d67 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -1990,7 +1990,9 @@ static int ieee80211_sta_join_ibss(struc
 		local->hw->reset_tsf(local->mdev);
 	}
 	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
-	memcpy(local->conf.client_bssid, bss->bssid, ETH_ALEN);
+	res = ieee80211_if_config(dev);
+	if (res)
+		return res;
 
 	local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
 
@@ -2345,11 +2347,20 @@ int ieee80211_sta_set_bssid(struct net_d
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_sta *ifsta;
+	int res;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	ifsta = &sdata->u.sta;
 
-	memcpy(ifsta->bssid, bssid, ETH_ALEN);
+	if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+		memcpy(ifsta->bssid, bssid, ETH_ALEN);
+		res = ieee80211_if_config(dev);
+		if (res) {
+			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
+			       "the low-level driver\n", dev->name);
+			return res;
+		}
+	}
 
 	if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
 		ifsta->bssid_set = 0;
-- 
1.3.0


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

* [PATCH 11/17] d80211: rename adm_status to radio_enabled
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (9 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 10/17] d80211: fix interface configuration Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 12/17] d80211: interface types changeable by SIOCSIWMODE Jiri Benc
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

PRISM2_PARAM_ADM_STATUS is not much descriptive name. This patch renames it
to PRISM2_PARAM_RADIO_ENABLED, sets radio_enabled to 1 by default (this is
no problem as radio must not be enabled until at least one network interface
is running) and removes automatic setting of adm_status when interface is in
a STA mode.

Later, PRISM2_PARAM_RADIO_ENABLED value can be removed and radio_enabled set
by SIOCSIWTXPOW handler (ie. by iwconfig txpower off).

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |    6 +++++-
 net/d80211/hostapd_ioctl.h   |    2 +-
 net/d80211/ieee80211.c       |    1 +
 net/d80211/ieee80211_ioctl.c |   11 +++++------
 4 files changed, 12 insertions(+), 8 deletions(-)

16a5dd7f47ba97ad3e19fe19a96a8d483dc29bbf
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 84abd7c..2ec31db 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -237,6 +237,10 @@ struct ieee80211_tx_status {
 };
 
 
+/**
+ * struct ieee80211_conf - configuration of a hardware
+ * @radio_enabled: when zero, driver is required to switch off the radio.
+ */
 struct ieee80211_conf {
 	int channel;			/* IEEE 802.11 channel number */
 	int freq;			/* MHz */
@@ -244,7 +248,7 @@ struct ieee80211_conf {
 
 	int phymode;			/* MODE_IEEE80211A, .. */
         unsigned int regulatory_domain;
-        int adm_status;
+	int radio_enabled;
 
         int beacon_int;
 
diff --git a/net/d80211/hostapd_ioctl.h b/net/d80211/hostapd_ioctl.h
index 028caf1..a462688 100644
--- a/net/d80211/hostapd_ioctl.h
+++ b/net/d80211/hostapd_ioctl.h
@@ -64,7 +64,7 @@ enum {
 	PRISM2_PARAM_TEST_MODE = 1007,
 	PRISM2_PARAM_NEXT_MODE = 1008,
 	PRISM2_PARAM_CLEAR_KEYS = 1009,
-	PRISM2_PARAM_ADM_STATUS = 1010,
+	PRISM2_PARAM_RADIO_ENABLED = 1010,
 	PRISM2_PARAM_ANTENNA_SEL = 1011,
 	PRISM2_PARAM_CALIB_INT = 1012,
         PRISM2_PARAM_ANTENNA_MODE = 1013,
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e6d4342..16a07d0 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4330,6 +4330,7 @@ struct net_device *ieee80211_alloc_hw(si
 	local->short_retry_limit = 7;
 	local->long_retry_limit = 4;
 	local->conf.calib_int = 60;
+	local->conf.radio_enabled = 1;
 	local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
 	local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
 
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 00efe47..6279a7a 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1166,11 +1166,11 @@ static int ieee80211_ioctl_set_regulator
 }
 
 
-static int ieee80211_ioctl_set_adm_status(struct net_device *dev,
-					  int val)
+static int ieee80211_ioctl_set_radio_enabled(struct net_device *dev,
+					     int val)
 {
         struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev);
-        conf->adm_status = val;
+	conf->radio_enabled = val;
         return ieee80211_hw_config(dev);
 }
 
@@ -1580,7 +1580,6 @@ static int ieee80211_init_client(struct 
 	if (ieee80211_regdom == 0x40)
 		channel_range = ieee80211_mkk_channels;
 	ieee80211_unmask_channels(dev);
-	ieee80211_ioctl_set_adm_status(dev, 1);
 	return 0;
 }
 
@@ -2312,8 +2311,8 @@ static int ieee80211_ioctl_prism2_param(
 		ret = ieee80211_ioctl_clear_keys(dev);
 		break;
 
-	case PRISM2_PARAM_ADM_STATUS:
-                ret = ieee80211_ioctl_set_adm_status(dev, value);
+	case PRISM2_PARAM_RADIO_ENABLED:
+		ret = ieee80211_ioctl_set_radio_enabled(dev, value);
 		break;
 
 	case PRISM2_PARAM_ANTENNA_SEL:
-- 
1.3.0


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

* [PATCH 12/17] d80211: interface types changeable by SIOCSIWMODE
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (10 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 11/17] d80211: rename adm_status to radio_enabled Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 13/17] d80211: master interface auto up/down Jiri Benc
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Allow type of interface to be set by SIOCSIWMODE. All of functions
responsible for adding/removing/initialization of interfaces were moved to
a new file ieee80211_iface.c. Function for removing interface was split into
two parts: one for deinitialization of the interface and one for
deallocation of the interface. That way, it is possible to change the type
of interface just by deinitializing and initializing it.

Also, remove set_mac_address callback to a driver, as it is not needed
anymore (drivers are notified about MAC addresses through add_interface
callback).

Please note, that although after this patch interfaces are fully independent
and driver can correctly control which combination is allowed, not all
multicast frames are received correctly by all respective interfaces. This
is addressed by subsequent patches.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |    3 
 net/d80211/Makefile          |    1 
 net/d80211/ieee80211.c       |  458 +++++-------------------------------------
 net/d80211/ieee80211_i.h     |   30 +--
 net/d80211/ieee80211_iface.c |  289 +++++++++++++++++++++++++++
 net/d80211/ieee80211_ioctl.c |  125 +++++++----
 net/d80211/ieee80211_sysfs.c |   12 +
 7 files changed, 435 insertions(+), 483 deletions(-)
 create mode 100644 net/d80211/ieee80211_iface.c

ef162ee22ef1564f76a9d67b8df647993806e72d
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 2ec31db..6894745 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -585,9 +585,6 @@ struct ieee80211_hw {
 	/* Configuration of test parameters */
 	int (*test_param)(struct net_device *dev, int param, int value);
 
-	/* Change MAC address. addr is pointer to struct sockaddr. */
-	int (*set_mac_address)(struct net_device *dev, void *addr);
-
         /* For devices that generate their own beacons and probe response
          * or association responses this updates the state of privacy_invoked
          * returns 0 for success or an error number */
diff --git a/net/d80211/Makefile b/net/d80211/Makefile
index 59d1d65..66bfcff 100644
--- a/net/d80211/Makefile
+++ b/net/d80211/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
 	ieee80211_scan.o \
 	ieee80211_sta.o \
 	ieee80211_dev.o \
+	ieee80211_iface.o \
 	ieee80211_sysfs.o \
 	michael.o \
 	tkip.o \
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 16a07d0..c20cb00 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1803,24 +1803,12 @@ static void ieee80211_tx_timeout(struct 
 
 static int ieee80211_set_mac_address(struct net_device *dev, void *addr)
 {
-	struct ieee80211_local *local = dev->priv;
 	struct sockaddr *a = addr;
-	struct list_head *ptr;
-	int res;
 
-	if (!local->hw->set_mac_address)
-		return -EOPNOTSUPP;
-
-	res = local->hw->set_mac_address(dev, addr);
-	if (res)
-		return res;
-
-	list_for_each(ptr, &local->sub_if_list)	{
-		struct ieee80211_sub_if_data *sdata =
-			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		memcpy(sdata->dev->dev_addr, a->sa_data, ETH_ALEN);
-	}
+	if (netif_running(dev))
+		return -EBUSY;
 
+	memcpy(dev->dev_addr, a->sa_data, ETH_ALEN);
 	return 0;
 }
 
@@ -1832,14 +1820,37 @@ static struct net_device_stats *ieee8021
 	return &(sdata->stats);
 }
 
+static inline int identical_mac_addr_allowed(int type1, int type2)
+{
+	return ((type1 == IEEE80211_IF_TYPE_AP &&
+		 type2 == IEEE80211_IF_TYPE_WDS) ||
+		(type1 == IEEE80211_IF_TYPE_WDS &&
+		 (type2 == IEEE80211_IF_TYPE_WDS ||
+		  type2 == IEEE80211_IF_TYPE_AP)));
+}
 
 static int ieee80211_open(struct net_device *dev)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_sub_if_data *sdata, *nsdata;
 	struct ieee80211_local *local = dev->priv;
 	int res;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	list_for_each_entry(nsdata, &local->sub_if_list, list) {
+		struct net_device *ndev = nsdata->dev;
+
+		if (ndev != dev && ndev != local->mdev &&
+		    ndev != local->wdev && ndev != local->apdev &&
+		    netif_running(ndev) &&
+		    memcmp(dev->dev_addr, ndev->dev_addr, ETH_ALEN) == 0 &&
+		    !identical_mac_addr_allowed(sdata->type, nsdata->type)) {
+			return -ENOTUNIQ;
+		}
+	}
+	if (sdata->type == IEEE80211_IF_TYPE_WDS &&
+	    memcmp(sdata->u.wds.remote_addr, "\0\0\0\0\0\0", ETH_ALEN) == 0)
+		return -ENOLINK;
+
 	if (local->hw->add_interface) {
 		struct ieee80211_if_init_conf conf;
 
@@ -1849,6 +1860,11 @@ static int ieee80211_open(struct net_dev
 		res = local->hw->add_interface(sdata->master, &conf);
 		if (res)
 			return res;
+	} else {
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
+			return -EOPNOTSUPP;
+		if (local->open_count > 0)
+			return -ENOBUFS;
 	}
 
         if (local->open_count == 0) {
@@ -3800,128 +3816,6 @@ static ieee80211_tx_handler ieee80211_tx
 };
 
 
-static void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
-{
-	/* Default values for sub-interface parameters */
-	sdata->drop_unencrypted = 0;
-	sdata->eapol = 1;
-}
-
-
-static struct net_device *ieee80211_if_add(struct net_device *dev,
-					   const char *name, int locked)
-{
-	struct net_device *wds_dev = NULL, *tmp_dev;
-        struct ieee80211_local *local = dev->priv;
-	struct ieee80211_sub_if_data *sdata = NULL, *sdata_parent;
-        int alloc_size;
-	int ret;
-	int i;
-
-	/* ensure 32-bit alignment of our private data and hw private data */
-	alloc_size = sizeof(struct net_device) + 3 +
-		sizeof(struct ieee80211_sub_if_data) + 3;
-
-        wds_dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL);
-        if (wds_dev == NULL)
-		return NULL;
-
-	memset(wds_dev, 0, alloc_size);
-	wds_dev->priv = local;
-	ether_setup(wds_dev);
-	if (strlen(name) == 0) {
-		i = 0;
-		do {
-			sprintf(wds_dev->name, "%s.%d", dev->name, i++);
-			tmp_dev = dev_get_by_name(wds_dev->name);
-			if (tmp_dev == NULL)
-				break;
-			dev_put(tmp_dev);
-		} while (i < 10000);
-	} else {
-                snprintf(wds_dev->name, IFNAMSIZ, "%s", name);
-	}
-
-	memcpy(wds_dev->dev_addr, dev->dev_addr, ETH_ALEN);
-	wds_dev->hard_start_xmit = ieee80211_subif_start_xmit;
-	wds_dev->wireless_handlers =
-		(struct iw_handler_def *) &ieee80211_iw_handler_def;
-        wds_dev->do_ioctl = ieee80211_ioctl;
-	wds_dev->change_mtu = ieee80211_change_mtu;
-        wds_dev->tx_timeout = ieee80211_tx_timeout;
-        wds_dev->get_stats = ieee80211_get_stats;
-        wds_dev->open = ieee80211_open;
-	wds_dev->stop = ieee80211_stop;
-	wds_dev->base_addr = dev->base_addr;
-	wds_dev->irq = dev->irq;
-	wds_dev->mem_start = dev->mem_start;
-	wds_dev->mem_end = dev->mem_end;
-	wds_dev->tx_queue_len = 0;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(wds_dev);
-	sdata->type = IEEE80211_IF_TYPE_AP;
-        sdata->master = local->mdev;
-        sdata->dev = wds_dev;
-	sdata->local = local;
-	memset(&sdata->stats, 0, sizeof(struct net_device_stats));
-	sdata_parent = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata_parent->type == IEEE80211_IF_TYPE_AP)
-		sdata->bss = &sdata_parent->u.ap;
-	else {
-		printk(KERN_DEBUG "%s: could not set BSS pointer for new "
-		       "interface %s\n", dev->name, wds_dev->name);
-	}
-	ieee80211_if_sdata_init(sdata);
-
-        if (locked)
-		ret = register_netdevice(wds_dev);
-	else
-		ret = register_netdev(wds_dev);
-	if (ret) {
-		kfree(wds_dev);
-		return NULL;
-	}
-
-        list_add(&sdata->list, &local->sub_if_list);
-
-        return wds_dev;
-}
-
-
-int ieee80211_if_add_wds(struct net_device *dev, const char *name,
-                         struct ieee80211_if_wds *wds, int locked)
-{
-        struct net_device *wds_dev = NULL;
-	struct ieee80211_sub_if_data *sdata = NULL;
-
-        if (strlen(name) != 0) {
-                wds_dev = dev_get_by_name(name);
-                if (wds_dev) {
-                        dev_put(wds_dev);
-                        return -EEXIST;
-                }
-        }
-
-        wds_dev = ieee80211_if_add(dev, name, locked);
-        if (wds_dev == NULL)
-                return -ENOANO;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(wds_dev);
-        sdata->type = IEEE80211_IF_TYPE_WDS;
-        memcpy(&sdata->u.wds, wds, sizeof(struct ieee80211_if_wds));
-
-#ifdef CONFIG_D80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG
-	       "%s: Added WDS Link to " MACSTR "\n",
-	       wds_dev->name, MAC2STR(sdata->u.wds.remote_addr));
-#endif /* CONFIG_D80211_VERBOSE_DEBUG */
-
-	ieee80211_proc_init_virtual(wds_dev);
-
-        return 0;
-}
-
-
 int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
 {
 	struct ieee80211_local *local = dev->priv;
@@ -3955,274 +3849,22 @@ static void ieee80211_if_init(struct net
 }
 
 
-int ieee80211_if_add_vlan(struct net_device *dev, const char *name,
-			  struct ieee80211_if_vlan *vlan, int locked)
-{
-        struct net_device *vlan_dev = NULL;
-        struct ieee80211_sub_if_data *sdata = NULL;
-
-        if (strlen(name) != 0) {
-                vlan_dev = dev_get_by_name(name);
-                if (vlan_dev) {
-                        dev_put(vlan_dev);
-                        return -EEXIST;
-                }
-        }
-
-        vlan_dev = ieee80211_if_add(dev, name, locked);
-        if (vlan_dev == NULL)
-                return -ENOANO;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(vlan_dev);
-        sdata->type = IEEE80211_IF_TYPE_VLAN;
-	ieee80211_proc_init_virtual(vlan_dev);
-        return 0;
-}
-
-
-static void ieee80211_if_ap_init(struct ieee80211_sub_if_data *sdata)
-{
-	sdata->type = IEEE80211_IF_TYPE_AP;
-	sdata->u.ap.dtim_period = 2;
-	sdata->u.ap.force_unicast_rateidx = -1;
-	sdata->u.ap.max_ratectrl_rateidx = -1;
-	skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
-	sdata->bss = &sdata->u.ap;
-}
-
-
-int ieee80211_if_add_ap(struct net_device *dev, const char *name, u8 *bssid,
-			  int locked)
-{
-	struct net_device *ap_dev = NULL;
-        struct ieee80211_sub_if_data *sdata = NULL;
-
-        if (strlen(name) != 0) {
-		ap_dev = dev_get_by_name(name);
-		if (ap_dev) {
-			dev_put(ap_dev);
-                        return -EEXIST;
-                }
-        }
-
-	ap_dev = ieee80211_if_add(dev, name, locked);
-	if (ap_dev == NULL)
-                return -ENOANO;
-
-	memcpy(ap_dev->dev_addr, bssid, ETH_ALEN);
-	sdata = IEEE80211_DEV_TO_SUB_IF(ap_dev);
-	ieee80211_if_ap_init(sdata);
-	ieee80211_proc_init_virtual(ap_dev);
-
-        return 0;
-}
-
-
-int ieee80211_if_add_sta(struct net_device *dev, const char *name, int locked)
-{
-	struct net_device *sta_dev;
-	struct ieee80211_sub_if_data *sdata;
-	struct ieee80211_if_sta *ifsta;
-
-	if (strlen(name) != 0) {
-		sta_dev = dev_get_by_name(name);
-		if (sta_dev) {
-			dev_put(sta_dev);
-			return -EEXIST;
-		}
-	}
-
-	sta_dev = ieee80211_if_add(dev, name, locked);
-	if (sta_dev == NULL)
-		return -ENOANO;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(sta_dev);
-	ifsta = &sdata->u.sta;
-	sdata->type = IEEE80211_IF_TYPE_STA;
-	ieee80211_proc_init_virtual(sta_dev);
-
-	init_timer(&ifsta->timer);
-	ifsta->timer.data = (unsigned long) sta_dev;
-	ifsta->timer.function = ieee80211_sta_timer;
-
-	ifsta->capab = WLAN_CAPABILITY_ESS;
-	ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
-		IEEE80211_AUTH_ALG_SHARED_KEY;
-	ifsta->create_ibss = 1;
-	ifsta->wmm_enabled = 1;
-
-	return 0;
-}
-
-
-static void ieee80211_if_del(struct ieee80211_local *local,
-			     struct ieee80211_sub_if_data *sdata, int locked)
-{
-        struct sta_info *sta;
-	u8 addr[ETH_ALEN];
-	int i;
-        struct list_head *ptr, *n;
-
-	memset(addr, 0xff, ETH_ALEN);
-	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-		if (!sdata->keys[i])
-			continue;
-#if 0
-		/* Low-level driver has probably disabled hw
-		 * already, so there is not really much point
-		 * in disabling the keys at this point. */
-		if (local->hw->set_key)
-			local->hw->set_key(dev, DISABLE_KEY, addr,
-					   local->keys[i], 0);
-#endif
-		ieee80211_key_free(sdata->keys[i]);
-	}
-
-	switch (sdata->type) {
-	case IEEE80211_IF_TYPE_AP:
-		/* Remove all virtual interfaces that use this BSS
-		 * as their sdata->bss */
-		list_for_each_safe(ptr, n, &local->sub_if_list) {
-			struct ieee80211_sub_if_data *tsdata =
-				list_entry(ptr, struct ieee80211_sub_if_data,
-					   list);
-
-			if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
-				printk(KERN_DEBUG "%s: removing virtual "
-				       "interface %s because its BSS interface"
-				       " is being removed\n",
-				       sdata->dev->name, tsdata->dev->name);
-				ieee80211_if_del(local, tsdata, locked);
-			}
-		}
-
-		kfree(sdata->u.ap.beacon_head);
-		kfree(sdata->u.ap.beacon_tail);
-
-		if (sdata->dev != local->mdev) {
-			struct sk_buff *skb;
-			while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
-				local->total_ps_buffered--;
-				dev_kfree_skb(skb);
-			}
-		}
-
-		break;
-	case IEEE80211_IF_TYPE_WDS:
-		sta = sta_info_get(local, sdata->u.wds.remote_addr);
-		if (sta) {
-			sta_info_release(local, sta);
-			sta_info_free(local, sta, 0);
-		} else {
-#ifdef CONFIG_D80211_VERBOSE_DEBUG
-			printk(KERN_DEBUG "%s: Someone had deleted my STA "
-			       "entry for the WDS link\n", local->mdev->name);
-#endif /* CONFIG_D80211_VERBOSE_DEBUG */
-		}
-		break;
-	case IEEE80211_IF_TYPE_STA:
-		del_timer_sync(&sdata->u.sta.timer);
-		if (local->scan_timer.data == (unsigned long) sdata->dev)
-			del_timer_sync(&local->scan_timer);
-		kfree(sdata->u.sta.extra_ie);
-		sdata->u.sta.extra_ie = NULL;
-		kfree(sdata->u.sta.assocreq_ies);
-		sdata->u.sta.assocreq_ies = NULL;
-		kfree(sdata->u.sta.assocresp_ies);
-		sdata->u.sta.assocresp_ies = NULL;
-		if (sdata->u.sta.probe_resp) {
-			dev_kfree_skb(sdata->u.sta.probe_resp);
-			sdata->u.sta.probe_resp = NULL;
-		}
-
-		break;
-	}
-
-	/* remove all STAs that are bound to this virtual interface */
-	sta_info_flush(local, sdata->dev);
-
-	list_del(&sdata->list);
-	ieee80211_proc_deinit_virtual(sdata->dev);
-	if (locked)
-		unregister_netdevice(sdata->dev);
-	else
-		unregister_netdev(sdata->dev);
-	/* Default data device and management device are allocated with the
-	 * master device. All other devices are separately allocated and will
-	 * be freed here. */
-	if (sdata->dev != local->mdev && sdata->dev != local->wdev &&
-	    sdata->dev != local->apdev)
-		kfree(sdata->dev);
-}
-
-
-static int ieee80211_if_remove(struct net_device *dev, const char *name,
-			       int id, int locked)
+/* Must not be called for wdev, mdev and apdev */
+void ieee80211_if_setup(struct net_device *dev)
 {
-        struct ieee80211_local *local = dev->priv;
-        struct list_head *ptr, *n;
-
-	/* Make sure not to touch sdata->master since it may
-	 * have already been deleted, etc. */
-
-	list_for_each_safe(ptr, n, &local->sub_if_list) {
-		struct ieee80211_sub_if_data *sdata =
-			list_entry(ptr, struct ieee80211_sub_if_data, list);
-
-		if (sdata->type == id && strcmp(name, sdata->dev->name) == 0) {
-			ieee80211_if_del(local, sdata, locked);
-			break;
-		}
-	}
-
-        return 0;
-}
-
-
-int ieee80211_if_remove_wds(struct net_device *dev, const char *name,
-			    int locked)
-{
-        return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_WDS, locked);
-}
-
-
-int ieee80211_if_remove_vlan(struct net_device *dev, const char *name,
-			     int locked)
-{
-        return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_VLAN, locked);
-}
-
-
-int ieee80211_if_remove_ap(struct net_device *dev, const char *name,
-			   int locked)
-{
-	return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_AP, locked);
-}
-
-
-int ieee80211_if_remove_sta(struct net_device *dev, const char *name,
-			    int locked)
-{
-	return ieee80211_if_remove(dev, name, IEEE80211_IF_TYPE_STA, locked);
-}
-
-
-int ieee80211_if_flush(struct net_device *dev, int locked)
-{
-        struct ieee80211_local *local = dev->priv;
-        struct list_head *ptr, *n;
-
-	list_for_each_safe(ptr, n, &local->sub_if_list) {
-		struct ieee80211_sub_if_data *sdata =
-			list_entry(ptr, struct ieee80211_sub_if_data, list);
-
-		if (sdata->dev != local->mdev &&
-		    sdata->dev != local->wdev &&
-		    sdata->dev != local->apdev)
-			ieee80211_if_del(local, sdata, locked);
-	}
-
-        return 0;
+	ether_setup(dev);
+	dev->hard_start_xmit = ieee80211_subif_start_xmit;
+	dev->wireless_handlers =
+		(struct iw_handler_def *) &ieee80211_iw_handler_def;
+	dev->do_ioctl = ieee80211_ioctl;
+	dev->set_mac_address = ieee80211_set_mac_address;
+	dev->change_mtu = ieee80211_change_mtu;
+	dev->tx_timeout = ieee80211_tx_timeout;
+	dev->get_stats = ieee80211_get_stats;
+	dev->open = ieee80211_open;
+	dev->stop = ieee80211_stop;
+	dev->tx_queue_len = 0;
+	dev->destructor = ieee80211_if_free;
 }
 
 
@@ -4357,7 +3999,7 @@ struct net_device *ieee80211_alloc_hw(si
         sdata->master = mdev;
         sdata->local = local;
 	ieee80211_if_sdata_init(sdata);
-	ieee80211_if_ap_init(sdata);
+	ieee80211_if_set_type(dev, IEEE80211_IF_TYPE_AP);
 	list_add_tail(&sdata->list, &local->sub_if_list);
 
 	if (strlen(dev->name) + 2 >= sizeof(dev->name))
@@ -4530,6 +4172,8 @@ int ieee80211_update_hw(struct net_devic
 	local->conf.freq = local->hw->modes[0].channels[0].freq;
 	local->conf.channel = local->hw->modes[0].channels[0].chan;
 	local->conf.channel_val = local->hw->modes[0].channels[0].val;
+
+	ieee80211_init_client(dev);
 	/* FIXME: Invoke config to allow driver to set the channel. */
 
 	return 0;
@@ -4556,7 +4200,7 @@ void ieee80211_unregister_hw(struct net_
 	list_for_each_safe(ptr, n, &local->sub_if_list) {
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		ieee80211_if_del(local, sdata, 0);
+		ieee80211_if_del(sdata->dev);
 	}
 
 	sta_info_stop(local);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 8fd0ac4..5116a88 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -493,18 +493,8 @@ void ieee80211_rx_mgmt(struct net_device
 		       struct ieee80211_rx_status *status, u32 msg_type);
 void ieee80211_prepare_rates(struct net_device *dev);
 void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
-int ieee80211_if_add_wds(struct net_device *dev, const char *name,
-			 struct ieee80211_if_wds *wds, int locked);
-int ieee80211_if_add_vlan(struct net_device *dev, const char *name,
-			  struct ieee80211_if_vlan *vlan, int locked);
-int ieee80211_if_add_ap(struct net_device *dev, const char *name, u8 *bssid,
-			int locked);
-
-int ieee80211_if_remove_wds(struct net_device *dev, const char *name, int locked);
-int ieee80211_if_remove_vlan(struct net_device *dev, const char *name, int locked);
-int ieee80211_if_remove_ap(struct net_device *dev, const char *name, int locked);
-int ieee80211_if_flush(struct net_device *dev, int locked);
 int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
+void ieee80211_if_setup(struct net_device *dev);
 
 /* ieee80211_ioctl.c */
 int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -540,13 +530,10 @@ #define CHAN_UTIL_HDR_LONG (202 * CHAN_U
 #define CHAN_UTIL_HDR_SHORT (40 * CHAN_UTIL_PER_USEC)
 
 
-
-/* ieee80211.c */
-int ieee80211_if_add_sta(struct net_device *dev, const char *name, int locked);
-int ieee80211_if_remove_sta(struct net_device *dev, const char *name, int locked);
 /* ieee80211_ioctl.c */
 int ieee80211_set_compression(struct ieee80211_local *local,
 			      struct net_device *dev, struct sta_info *sta);
+int ieee80211_init_client(struct net_device *dev);
 /* ieee80211_sta.c */
 void ieee80211_sta_timer(unsigned long ptr);
 void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
@@ -573,6 +560,19 @@ void ieee80211_dev_free_index(struct iee
 struct ieee80211_local *ieee80211_dev_find(int index);
 int ieee80211_dev_find_index(struct ieee80211_local *local);
 
+/* ieee80211_iface.c */
+int ieee80211_if_add(struct net_device *dev, const char *name,
+		     struct net_device **new_dev);
+void ieee80211_if_set_type(struct net_device *dev, int type);
+void ieee80211_if_reinit(struct net_device *dev);
+void __ieee80211_if_del(struct ieee80211_local *local,
+			struct ieee80211_sub_if_data *sdata);
+void ieee80211_if_del(struct net_device *dev);
+int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
+void ieee80211_if_free(struct net_device *dev);
+void ieee80211_if_flush(struct net_device *dev);
+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+
 /* ieee80211_sysfs.c */
 int ieee80211_register_sysfs(struct ieee80211_local *local);
 void ieee80211_unregister_sysfs(struct ieee80211_local *local);
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
new file mode 100644
index 0000000..917428e
--- /dev/null
+++ b/net/d80211/ieee80211_iface.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/d80211.h>
+#include <net/d80211_mgmt.h>
+#include "ieee80211_i.h"
+#include "ieee80211_proc.h"
+#include "sta_info.h"
+
+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+{
+	/* Default values for sub-interface parameters */
+	sdata->drop_unencrypted = 0;
+	sdata->eapol = 1;
+}
+
+/* Must be called with rtnl lock held. */
+int ieee80211_if_add(struct net_device *dev, const char *name,
+		     struct net_device **new_dev)
+{
+	struct net_device *ndev, *tmp_dev;
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = NULL, *sdata_parent;
+	int alloc_size;
+	int ret;
+	int i;
+
+	ASSERT_RTNL();
+	/* ensure 32-bit alignment of our private data and hw private data */
+	alloc_size = sizeof(struct net_device) + 3 +
+		sizeof(struct ieee80211_sub_if_data) + 3;
+
+	ndev = *new_dev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL);
+	if (ndev == NULL)
+		return -ENOMEM;
+
+	ndev->priv = local;
+	if (strlen(name) == 0) {
+		i = 0;
+		do {
+			sprintf(ndev->name, "%s.%d", dev->name, i++);
+			tmp_dev = dev_get_by_name(ndev->name);
+			if (tmp_dev == NULL)
+				break;
+			dev_put(tmp_dev);
+		} while (i < 10000);
+	} else {
+		snprintf(ndev->name, IFNAMSIZ, "%s", name);
+	}
+
+	memcpy(ndev->dev_addr, dev->dev_addr, ETH_ALEN);
+	ndev->base_addr = dev->base_addr;
+	ndev->irq = dev->irq;
+	ndev->mem_start = dev->mem_start;
+	ndev->mem_end = dev->mem_end;
+	ieee80211_if_setup(ndev);
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+	sdata->type = IEEE80211_IF_TYPE_AP;
+	sdata->master = local->mdev;
+	sdata->dev = ndev;
+	sdata->local = local;
+	sdata_parent = IEEE80211_DEV_TO_SUB_IF(dev);
+	ieee80211_if_sdata_init(sdata);
+
+	ret = register_netdevice(ndev);
+	if (ret) {
+		kfree(ndev);
+		*new_dev = NULL;
+		return ret;
+	}
+
+	list_add(&sdata->list, &local->sub_if_list);
+	ieee80211_proc_init_virtual(ndev);
+
+	return 0;
+}
+
+void ieee80211_if_set_type(struct net_device *dev, int type)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	sdata->type = type;
+	switch (type) {
+	case IEEE80211_IF_TYPE_WDS:
+		sdata->bss = NULL;
+		break;
+	case IEEE80211_IF_TYPE_VLAN:
+		break;
+	case IEEE80211_IF_TYPE_AP:
+		sdata->u.ap.dtim_period = 2;
+		sdata->u.ap.force_unicast_rateidx = -1;
+		sdata->u.ap.max_ratectrl_rateidx = -1;
+		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+		sdata->bss = &sdata->u.ap;
+		break;
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS: {
+		struct ieee80211_sub_if_data *msdata;
+		struct ieee80211_if_sta *ifsta;
+
+		ifsta = &sdata->u.sta;
+		init_timer(&ifsta->timer);
+		ifsta->timer.data = (unsigned long) dev;
+		ifsta->timer.function = ieee80211_sta_timer;
+
+		ifsta->capab = WLAN_CAPABILITY_ESS;
+		ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
+			IEEE80211_AUTH_ALG_SHARED_KEY;
+		ifsta->create_ibss = 1;
+		ifsta->wmm_enabled = 1;
+
+		msdata = IEEE80211_DEV_TO_SUB_IF(sdata->master);
+		sdata->bss = &msdata->u.ap;
+		break;
+	}
+	default:
+		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
+		       dev->name, __FUNCTION__, type);
+	}
+}
+
+/* Must be called with rtnl lock held. */
+void ieee80211_if_reinit(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct sta_info *sta;
+	int i;
+
+	ASSERT_RTNL();
+	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+		if (!sdata->keys[i])
+			continue;
+#if 0
+		/* The interface is down at the moment, so there is not
+		 * really much point in disabling the keys at this point. */
+		memset(addr, 0xff, ETH_ALEN);
+		if (local->hw->set_key)
+			local->hw->set_key(dev, DISABLE_KEY, addr,
+					   local->keys[i], 0);
+#endif
+		ieee80211_key_free(sdata->keys[i]);
+	}
+
+	switch (sdata->type) {
+	case IEEE80211_IF_TYPE_AP: {
+		/* Remove all virtual interfaces that use this BSS
+		 * as their sdata->bss */
+		struct ieee80211_sub_if_data *tsdata, *n;
+
+		list_for_each_entry_safe(tsdata, n, &local->sub_if_list, list) {
+			if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
+				printk(KERN_DEBUG "%s: removing virtual "
+				       "interface %s because its BSS interface"
+				       " is being removed\n",
+				       sdata->dev->name, tsdata->dev->name);
+				__ieee80211_if_del(local, tsdata);
+			}
+		}
+
+		kfree(sdata->u.ap.beacon_head);
+		kfree(sdata->u.ap.beacon_tail);
+
+		if (dev != local->mdev) {
+			struct sk_buff *skb;
+			while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+				local->total_ps_buffered--;
+				dev_kfree_skb(skb);
+			}
+		}
+
+		break;
+	}
+	case IEEE80211_IF_TYPE_WDS:
+		sta = sta_info_get(local, sdata->u.wds.remote_addr);
+		if (sta) {
+			sta_info_release(local, sta);
+			sta_info_free(local, sta, 0);
+		} else {
+#ifdef CONFIG_D80211_VERBOSE_DEBUG
+			printk(KERN_DEBUG "%s: Someone had deleted my STA "
+			       "entry for the WDS link\n", dev->name);
+#endif /* CONFIG_D80211_VERBOSE_DEBUG */
+		}
+		break;
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS:
+		del_timer_sync(&sdata->u.sta.timer);
+		if (local->scan_timer.data == (unsigned long) sdata->dev)
+			del_timer_sync(&local->scan_timer);
+		kfree(sdata->u.sta.extra_ie);
+		sdata->u.sta.extra_ie = NULL;
+		kfree(sdata->u.sta.assocreq_ies);
+		sdata->u.sta.assocreq_ies = NULL;
+		kfree(sdata->u.sta.assocresp_ies);
+		sdata->u.sta.assocresp_ies = NULL;
+		if (sdata->u.sta.probe_resp) {
+			dev_kfree_skb(sdata->u.sta.probe_resp);
+			sdata->u.sta.probe_resp = NULL;
+		}
+
+		break;
+	}
+
+	/* remove all STAs that are bound to this virtual interface */
+	sta_info_flush(local, dev);
+
+	memset(&sdata->u, 0, sizeof(sdata->u));
+	ieee80211_if_sdata_init(sdata);
+}
+
+/* Must be called with rtnl lock held. */
+void __ieee80211_if_del(struct ieee80211_local *local,
+			struct ieee80211_sub_if_data *sdata)
+{
+	struct net_device *dev = sdata->dev;
+
+	ieee80211_if_reinit(dev);
+	list_del(&sdata->list);
+	ieee80211_proc_deinit_virtual(dev);
+	unregister_netdevice(dev);
+	/* Default data device and management device are allocated with the
+	 * master device. All other devices are separately allocated and will
+	 * be freed by net_device->destructor (i. e. ieee80211_if_free). */
+}
+
+/* Must be called with rtnl lock held. */
+int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata, *n;
+
+	ASSERT_RTNL();
+
+	/* Make sure not to touch sdata->master since it may
+	 * have already been deleted, etc. */
+
+	list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) {
+		if ((sdata->type == id || id == -1) &&
+		    strcmp(name, sdata->dev->name) == 0 &&
+		    sdata->dev != local->mdev &&
+		    sdata->dev != local->wdev &&
+		    sdata->dev != local->apdev) {
+			__ieee80211_if_del(local, sdata);
+			return 0;
+		}
+	}
+	return -ENODEV;
+}
+
+void ieee80211_if_free(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+
+	BUG_ON(dev == local->mdev || dev == local->wdev || dev == local->apdev);
+	kfree(dev);
+}
+
+/* Must be called with rtnl lock held. */
+void ieee80211_if_flush(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata, *n;
+
+	ASSERT_RTNL();
+	list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) {
+		__ieee80211_if_del(local, sdata);
+	}
+}
+
+void ieee80211_if_del(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	rtnl_lock();
+	__ieee80211_if_del(local, sdata);
+	rtnl_unlock();
+}
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 6279a7a..dfa0ef7 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -922,30 +922,39 @@ static int ieee80211_ioctl_add_if(struct
 {
 	u8 *pos = param->u.if_info.data;
         int left = param_len - ((u8 *) pos - (u8 *) param);
+	struct net_device *new_dev;
+	int res;
 
+	printk(KERN_WARNING "PRISM2_HOSTAPD_ADD_IF ioctl is deprecated!");
         if (param->u.if_info.type == HOSTAP_IF_WDS) {
-                struct ieee80211_if_wds iwds;
                 struct hostapd_if_wds *wds =
 			(struct hostapd_if_wds *) param->u.if_info.data;
 
-                if (left < sizeof(struct ieee80211_if_wds))
+                if (left < sizeof(struct hostapd_if_wds))
                         return -EPROTO;
 
-		memcpy(iwds.remote_addr, wds->remote_addr, ETH_ALEN);
-
-		return ieee80211_if_add_wds(dev, param->u.if_info.name,
-					    &iwds, 1);
+		res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+		if (res)
+			return res;
+		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_WDS);
+		res = ieee80211_if_update_wds(new_dev, wds->remote_addr);
+		if (res)
+			ieee80211_if_del(new_dev);
+		return res;
 	} else if (param->u.if_info.type == HOSTAP_IF_VLAN) {
-		struct hostapd_if_vlan *vlan = (struct hostapd_if_vlan *) pos;
-		struct ieee80211_if_vlan ivlan;
-
 		if (left < sizeof(struct hostapd_if_vlan))
 			return -EPROTO;
 
-                ivlan.id = vlan->id;
-
-		return ieee80211_if_add_vlan(dev, param->u.if_info.name,
-					     &ivlan, 1);
+		res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+		if (res)
+			return res;
+		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_VLAN);
+#if 0
+		res = ieee80211_if_update_vlan(new_dev, vlan->id);
+		if (res)
+			ieee80211_if_del(new_dev);
+#endif
+		return res;
         } else if (param->u.if_info.type == HOSTAP_IF_BSS) {
                 struct hostapd_if_bss *bss =
 			(struct hostapd_if_bss *) param->u.if_info.data;
@@ -953,8 +962,12 @@ static int ieee80211_ioctl_add_if(struct
                 if (left < sizeof(struct hostapd_if_bss))
                         return -EPROTO;
 
-		return ieee80211_if_add_ap(dev, param->u.if_info.name,
-					     bss->bssid, 1);
+		res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+		if (res)
+			return res;
+		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_AP);
+		memcpy(new_dev->dev_addr, bss->bssid, ETH_ALEN);
+		return 0;
         } else if (param->u.if_info.type == HOSTAP_IF_STA) {
 #if 0
                 struct hostapd_if_sta *sta =
@@ -964,7 +977,11 @@ #endif
                 if (left < sizeof(struct hostapd_if_sta))
                         return -EPROTO;
 
-		return ieee80211_if_add_sta(dev, param->u.if_info.name, 1);
+		res = ieee80211_if_add(dev, param->u.if_info.name, &new_dev);
+		if (res)
+			return res;
+		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_STA);
+		return 0;
 	} else
                 return -EINVAL;
 
@@ -975,17 +992,14 @@ #endif
 static int ieee80211_ioctl_remove_if(struct net_device *dev,
 				     struct prism2_hostapd_param *param)
 {
-	if (param->u.if_info.type == HOSTAP_IF_WDS) {
-		return ieee80211_if_remove_wds(dev, param->u.if_info.name, 1);
-	} else if (param->u.if_info.type == HOSTAP_IF_VLAN) {
-		return ieee80211_if_remove_vlan(dev, param->u.if_info.name, 1);
-	} else if (param->u.if_info.type == HOSTAP_IF_BSS) {
-		return ieee80211_if_remove_ap(dev, param->u.if_info.name, 1);
-	} else if (param->u.if_info.type == HOSTAP_IF_STA) {
-		return ieee80211_if_remove_sta(dev, param->u.if_info.name, 1);
-	} else {
+	if (param->u.if_info.type != HOSTAP_IF_WDS &&
+	    param->u.if_info.type != HOSTAP_IF_VLAN &&
+	    param->u.if_info.type != HOSTAP_IF_BSS &&
+	    param->u.if_info.type != HOSTAP_IF_STA) {
                 return -EINVAL;
 	}
+	return ieee80211_if_remove(dev, param->u.if_info.name,
+				   param->u.if_info.type);
 }
 
 
@@ -1027,7 +1041,8 @@ static int ieee80211_ioctl_update_if(str
 static int ieee80211_ioctl_flush_ifs(struct net_device *dev,
 				     struct prism2_hostapd_param *param)
 {
-	return ieee80211_if_flush(dev, 1);
+	ieee80211_if_flush(dev);
+	return 0;
 }
 
 
@@ -1575,7 +1590,7 @@ static int ieee80211_unmask_channels(str
 }
 
 
-static int ieee80211_init_client(struct net_device *dev)
+int ieee80211_init_client(struct net_device *dev)
 {
 	if (ieee80211_regdom == 0x40)
 		channel_range = ieee80211_mkk_channels;
@@ -1588,35 +1603,39 @@ static int ieee80211_ioctl_siwmode(struc
 				   struct iw_request_info *info,
 				   __u32 *mode, char *extra)
 {
-#if 0
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int type;
 
-	if (!ieee80211_is_client_mode(local->conf.mode) &&
-	    ieee80211_is_client_mode(*mode)) {
-		ieee80211_init_client(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_VLAN)
+		return -EOPNOTSUPP;
+	if (netif_running(dev))
+		return -EBUSY;
+
+	switch (*mode) {
+	case IW_MODE_MASTER:
+		type = IEEE80211_IF_TYPE_AP;
+		break;
+	case IW_MODE_INFRA:
+		type = IEEE80211_IF_TYPE_STA;
+		break;
+	case IW_MODE_ADHOC:
+		type = IEEE80211_IF_TYPE_IBSS;
+		break;
+	case IW_MODE_MONITOR:
+		type = IEEE80211_IF_TYPE_MNTR;
+		break;
+	case IW_MODE_REPEAT:
+		type = IEEE80211_IF_TYPE_WDS;
+		break;
+	default:
+		return -EINVAL;
 	}
-	if (local->conf.mode != *mode) {
-		struct ieee80211_sub_if_data *sdata =
-			IEEE80211_DEV_TO_SUB_IF(dev);
-		sta_info_flush(local, NULL);
-		if (local->conf.mode == IW_MODE_ADHOC &&
-		    sdata->type == IEEE80211_IF_TYPE_STA) {
-			/* Clear drop_unencrypted when leaving adhoc mode since
-			 * only adhoc mode is using automatic setting for this
-			 * in 80211.o. */
-			sdata->drop_unencrypted = 0;
-		}
-		if (*mode == IW_MODE_MASTER) {
-			/* AP mode does not currently use ACM bits to limit
-			 * TX, so clear the bitfield here. */
-			local->wmm_acm = 0;
-		}
+
+	if (type != sdata->type) {
+		ieee80211_if_reinit(dev);
+		ieee80211_if_set_type(dev, type);
 	}
-	local->conf.mode = *mode;
-	return ieee80211_hw_config(dev);
-#else
-	return -EOPNOTSUPP;
-#endif
+	return 0;
 }
 
 
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 082404f..546e2b7 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -22,17 +22,17 @@ static ssize_t store_add_iface(struct cl
 			       const char *buf, size_t len)
 {
 	struct ieee80211_local *local = to_ieee80211_local(dev);
+	struct net_device *new_dev;
 	int res;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 	if (len > IFNAMSIZ)
 		return -EINVAL;
-	/* Cannot call ieee80211_if_add_sta() with 'locked' parameter equal
-	 * to zero as it would lead to call to register_netdev() and
-	 * interpreting '%d' character in an interface name. */
 	rtnl_lock();
-	res = ieee80211_if_add_sta(local->mdev, buf, 1);
+	res = ieee80211_if_add(local->mdev, buf, &new_dev);
+	if (res == 0)
+		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_STA);
 	rtnl_unlock();
 	return res < 0 ? res : len;
 }
@@ -47,7 +47,9 @@ static ssize_t store_remove_iface(struct
 		return -EPERM;
 	if (len > IFNAMSIZ)
 		return -EINVAL;
-	res = ieee80211_if_remove_sta(local->mdev, buf, 0);
+	rtnl_lock();
+	res = ieee80211_if_remove(local->mdev, buf, -1);
+	rtnl_unlock();
 	return res < 0 ? res : len;
 }
 
-- 
1.3.0


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

* [PATCH 13/17] d80211: master interface auto up/down
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (11 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 12/17] d80211: interface types changeable by SIOCSIWMODE Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 14/17] d80211: set_multicast_list Jiri Benc
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

There is no reason to put master interface to UP/DOWN state manually.

Calling of hw->open and hw->stop callbacks logically belongs to
ieee80211_master_open and ieee80211_master_stop functions, but then we need
to refuse putting master interface to UP state when there is no other
interface running, and similarly, to refuse putting master interface DOWN
when there are other interfaces running. Because the second is not possible,
hw->open and hw->stop need to be called from ieee80211_open/ieee80211_stop.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c |   57 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 44 insertions(+), 13 deletions(-)

e5df634b3ae1c945076820434d8dcf897c0eb574
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index c20cb00..ea71b6c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1829,10 +1829,38 @@ static inline int identical_mac_addr_all
 		  type2 == IEEE80211_IF_TYPE_AP)));
 }
 
+static int ieee80211_master_open(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata;
+	int res = -EOPNOTSUPP;
+
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		if (sdata->dev != dev && netif_running(sdata->dev)) {
+			res = 0;
+			break;
+		}
+	}
+	return res;
+}
+
+static int ieee80211_master_stop(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata;
+
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		if (sdata->dev != dev && netif_running(sdata->dev))
+			return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
 static int ieee80211_open(struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata, *nsdata;
 	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_if_init_conf conf;
 	int res;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1852,8 +1880,6 @@ static int ieee80211_open(struct net_dev
 		return -ENOLINK;
 
 	if (local->hw->add_interface) {
-		struct ieee80211_if_init_conf conf;
-
 		conf.if_id = dev->ifindex;
 		conf.type = sdata->type;
 		conf.mac_addr = dev->dev_addr;
@@ -1868,10 +1894,18 @@ static int ieee80211_open(struct net_dev
 	}
 
         if (local->open_count == 0) {
-		if (local->hw->open) {
+		res = 0;
+		if (local->hw->open)
 			res = local->hw->open(sdata->master);
-			if (res)
-				return res;
+		if (res == 0) {
+			res = dev_open(sdata->master);
+			if (res && local->hw->stop)
+				local->hw->stop(sdata->master);
+		}
+		if (res) {
+			if (local->hw->remove_interface)
+				local->hw->remove_interface(dev, &conf);
+			return res;
 		}
 		ieee80211_init_scan(sdata->master);
 	}
@@ -1886,7 +1920,6 @@ static int ieee80211_stop(struct net_dev
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_local *local = dev->priv;
-	int res;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -1895,11 +1928,9 @@ static int ieee80211_stop(struct net_dev
 	local->open_count--;
         if (local->open_count == 0) {
 		ieee80211_stop_scan(sdata->master);
-		if (local->hw->stop) {
-			res = local->hw->stop(sdata->master);
-			if (res)
-				return res;
-		}
+		dev_close(sdata->master);
+		if (local->hw->stop)
+			local->hw->stop(sdata->master);
         }
 	if (local->hw->remove_interface) {
 		struct ieee80211_if_init_conf conf;
@@ -4035,8 +4066,8 @@ struct net_device *ieee80211_alloc_hw(si
 	mdev->change_mtu = ieee80211_change_mtu;
         mdev->tx_timeout = ieee80211_tx_timeout;
         mdev->get_stats = ieee80211_get_stats;
-        mdev->open = ieee80211_open;
-	mdev->stop = ieee80211_stop;
+	mdev->open = ieee80211_master_open;
+	mdev->stop = ieee80211_master_stop;
 	mdev->type = ARPHRD_IEEE80211;
         mdev->hard_header_parse = header_parse_80211;
 	sprintf(mdev->name, "%s.11", dev->name);
-- 
1.3.0


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

* [PATCH 14/17] d80211: set_multicast_list
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (12 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 13/17] d80211: master interface auto up/down Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 15/17] d80211: fix handling of received frames Jiri Benc
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Add set_multicast_list callback. The version of set_multicast_list in
struct net_device cannot be used by a driver, because the driver is
interested in cumulative flags and cumulative multicast list from all
interfaces.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |   24 ++++++++++++++
 net/d80211/ieee80211.c       |   71 ++++++++++++++++++++++++++++++++++++++++++
 net/d80211/ieee80211_i.h     |    8 +++++
 net/d80211/ieee80211_iface.c |    1 +
 4 files changed, 104 insertions(+), 0 deletions(-)

9ada6736d81619ac81ea1ce283f47c365fe3b24f
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 6894745..7bc66b5 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -532,6 +532,13 @@ struct ieee80211_hw {
 	int (*config_interface)(struct net_device *dev, int if_id,
 				struct ieee80211_if_conf *conf);
 
+	/* ieee80211 drivers should use this and not the function in
+	 * net_device. dev->flags, dev->mc_count and dev->mc_list must not
+	 * be used; use passed parameters and ieee80211_get_mc_list_item()
+	 * instead. */
+	void (*set_multicast_list)(struct net_device *dev,
+				   unsigned short flags, int mc_count);
+
 	/* Set TIM bit handler. If the hardware/firmware takes care of beacon
 	 * generation, IEEE 802.11 code uses this function to tell the
 	 * low-level to set (or clear if set==0) TIM bit for the given aid. If
@@ -775,6 +782,23 @@ typedef enum {
 } Netif_Oper;
 int ieee80211_netif_oper(struct net_device *dev, Netif_Oper op);
 
+/**
+ * ieee80211_get_mc_list_item - iteration over items in multicast list
+ * @dev: pointer to &struct net_device as obtained from
+ *	ieee80211_alloc_hw().
+ * @prev: value returned by previous call to ieee80211_get_mc_list_item() or
+ *	NULL to start a new iteration.
+ * @ptr: pointer to buffer of void * type for internal usage of
+ *	ieee80211_get_mc_list_item().
+ *
+ * Iterates over items in multicast list of given device. To get the first
+ * item, pass NULL in @prev and in *@ptr. In subsequent calls, pass the
+ * value returned by previous call in @prev. Don't alter *@ptr during
+ * iteration. When there are no more items, NULL is returned.
+ */
+struct dev_mc_list *ieee80211_get_mc_list_item(struct net_device *dev,
+					       struct dev_mc_list *prev,
+					       void **ptr);
 
 /*
  * Function to get hardware configuration information
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index ea71b6c..fbca700 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1812,6 +1812,75 @@ static int ieee80211_set_mac_address(str
 	return 0;
 }
 
+static void ieee80211_set_multicast_list(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->priv;
+        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	unsigned short flags;
+
+	if (((dev->flags & IFF_ALLMULTI) != 0) ^ (sdata->allmulti != 0)) {
+		if (sdata->allmulti) {
+			sdata->allmulti = 0;
+			local->iff_allmultis--;
+		} else {
+			sdata->allmulti = 1;
+			local->iff_allmultis++;
+		}
+	}
+	if (((dev->flags & IFF_PROMISC) != 0) ^ (sdata->promisc != 0)) {
+		if (sdata->promisc) {
+			sdata->promisc = 0;
+			local->iff_promiscs--;
+		} else {
+			sdata->promisc = 1;
+			local->iff_promiscs++;
+		}
+	}
+	if (dev->mc_count != sdata->mc_count) {
+		local->mc_count = local->mc_count - sdata->mc_count +
+				  dev->mc_count;
+		sdata->mc_count = dev->mc_count;
+	}
+	if (local->hw->set_multicast_list) {
+		flags = sdata->master->flags;
+		if (local->iff_allmultis)
+			flags |= IFF_ALLMULTI;
+		if (local->iff_promiscs)
+			flags |= IFF_PROMISC;
+		local->hw->set_multicast_list(sdata->master, flags,
+					      local->mc_count);
+	}
+}
+
+struct dev_mc_list *ieee80211_get_mc_list_item(struct net_device *dev,
+					       struct dev_mc_list *prev,
+					       void **ptr)
+{
+	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata = *ptr;
+	struct dev_mc_list *mc;
+
+	if (!prev) {
+		WARN_ON(sdata);
+		sdata = NULL;
+	}
+	if (!prev || !prev->next) {
+		if (sdata)
+			sdata = list_entry(sdata->list.next,
+					   struct ieee80211_sub_if_data, list);
+		else
+			sdata = list_entry(local->sub_if_list.next,
+					   struct ieee80211_sub_if_data, list);
+		if (&sdata->list != &local->sub_if_list)
+			mc = sdata->dev->mc_list;
+		else
+			mc = NULL;
+	} else
+		mc = prev->next;
+
+	*ptr = sdata;
+	return mc;
+}
 
 static struct net_device_stats *ieee80211_get_stats(struct net_device *dev)
 {
@@ -3889,6 +3958,7 @@ void ieee80211_if_setup(struct net_devic
 		(struct iw_handler_def *) &ieee80211_iw_handler_def;
 	dev->do_ioctl = ieee80211_ioctl;
 	dev->set_mac_address = ieee80211_set_mac_address;
+	dev->set_multicast_list = ieee80211_set_multicast_list;
 	dev->change_mtu = ieee80211_change_mtu;
 	dev->tx_timeout = ieee80211_tx_timeout;
 	dev->get_stats = ieee80211_get_stats;
@@ -4449,6 +4519,7 @@ EXPORT_SYMBOL(ieee80211_rate_control_unr
 EXPORT_SYMBOL(sta_info_get);
 EXPORT_SYMBOL(sta_info_release);
 EXPORT_SYMBOL(ieee80211_radar_status);
+EXPORT_SYMBOL(ieee80211_get_mc_list_item);
 
 module_init(ieee80211_init);
 module_exit(ieee80211_exit);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 5116a88..37d533d 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -264,6 +264,10 @@ struct ieee80211_sub_if_data {
         struct net_device *master;
         struct ieee80211_local *local;
 
+	int mc_count;
+	unsigned allmulti:1;
+	unsigned promisc:1;
+
         struct net_device_stats stats;
 	int drop_unencrypted;
 	int eapol; /* 0 = process EAPOL frames as normal data frames,
@@ -327,6 +331,10 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 	struct sta_info *sta_hash[STA_HASH_SIZE];
 	struct timer_list sta_cleanup;
 
+	int mc_count;	/* total count of multicast entries in all interfaces */
+	int iff_allmultis, iff_promiscs;
+			/* number of interfaces with corresponding IFF_ flags */
+
 	/* Current rate table. This is a pointer to hw->modes structure. */
 	struct ieee80211_rate *curr_rates;
 	int num_curr_rates;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 917428e..2151bd9 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -62,6 +62,7 @@ int ieee80211_if_add(struct net_device *
 	ndev->irq = dev->irq;
 	ndev->mem_start = dev->mem_start;
 	ndev->mem_end = dev->mem_end;
+	ndev->flags = dev->flags & IFF_MULTICAST;
 	ieee80211_if_setup(ndev);
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
-- 
1.3.0


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

* [PATCH 15/17] d80211: fix handling of received frames
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (13 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 14/17] d80211: set_multicast_list Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:11 ` [PATCH 16/17] d80211: fix monitor interfaces Jiri Benc
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Make sure that every frame reaches every interface it belongs to.
Previously, some packet (most notably multicast ones) were not delivered to
all interface they should be delivered to. This also allows monitor
interfaces to work easily, even together with regular interfaces.

On a typical setup (i.e. one or two interfaces only) this patch shouldn't
have significant impact on performance. However, on a setup with great
number of interfaces, things will probably slow down. This is not a problem
with design of this patch - things can be relatively easily sped up later.
See related comment in 'd80211: remove obsolete stuff' patch.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c |  338 +++++++++++++++++-------------------------------
 1 files changed, 121 insertions(+), 217 deletions(-)

5aa4f5e0b7654f03d39977ac1212356d6b6f3fa7
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index fbca700..e2a42af 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -2020,73 +2020,10 @@ static int header_parse_80211(struct sk_
 	return ETH_ALEN;
 }
 
-
-static struct net_device *
-ieee80211_get_wds_dev(struct ieee80211_local *local, u8 *addr)
+static inline int ieee80211_bssid_match(u8 *raddr, u8 *addr)
 {
-	struct list_head *ptr;
-
-	list_for_each(ptr, &local->sub_if_list)	{
-		struct ieee80211_sub_if_data *sdata =
-			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type == IEEE80211_IF_TYPE_WDS &&
-		    memcmp(addr, sdata->u.wds.remote_addr, ETH_ALEN) == 0)
-			return sdata->dev;
-	}
-
-	return NULL;
-}
-
-
-static struct net_device * ieee80211_own_bssid(struct ieee80211_local *local,
-					       u8 *addr)
-{
-	struct net_device *dev = NULL;
-	struct ieee80211_sub_if_data *sdata;
-
-	spin_lock_bh(&local->sub_if_lock);
-	list_for_each_entry(sdata, &local->sub_if_list, list) {
-		if (sdata->type == IEEE80211_IF_TYPE_AP &&
-		    memcmp(addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
-			dev = sdata->dev;
-			break;
-		}
-	}
-	spin_unlock_bh(&local->sub_if_lock);
-
-	return dev;
-}
-
-
-static struct net_device * ieee80211_sta_bssid(struct ieee80211_local *local,
-					       u8 *addr, u8 *a1,
-					       int *sta_multicast)
-{
-	struct list_head *ptr;
-	int multicast;
-
-	multicast = a1[0] & 0x01;
-
-	/* Could not find station interface, resort to O(n) lookup. */
-	list_for_each(ptr, &local->sub_if_list) {
-		struct ieee80211_sub_if_data *sdata =
-			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type != IEEE80211_IF_TYPE_STA &&
-		    sdata->type != IEEE80211_IF_TYPE_IBSS)
-			continue;
-		if (!multicast &&
-		    memcmp(a1, sdata->dev->dev_addr, ETH_ALEN) != 0)
-			continue;
-
-		if (memcmp(addr, sdata->u.sta.bssid, ETH_ALEN) == 0 ||
-		    (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0 &&
-		     sdata->type == IEEE80211_IF_TYPE_IBSS)) {
-			*sta_multicast = multicast;
-			return sdata->dev;
-		}
-	}
-
-	return NULL;
+	return memcmp(raddr, addr, ETH_ALEN) == 0 ||
+	       is_broadcast_ether_addr(raddr);
 }
 
 
@@ -2128,8 +2065,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr3, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
-		if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP ||
-			     !ieee80211_own_bssid(local, hdr->addr1))) {
+		if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP)) {
 			printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
 			       MACSTR " SA=" MACSTR " DA=" MACSTR ")\n",
 			       dev->name, MAC2STR(hdr->addr1),
@@ -2142,8 +2078,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr3, ETH_ALEN);
 		memcpy(src, hdr->addr4, ETH_ALEN);
 
-		dev = ieee80211_get_wds_dev(local, hdr->addr2);
-		if (!dev || memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) != 0) {
+		if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) {
 			printk(KERN_DEBUG "%s: dropped FromDS&ToDS frame (RA="
 			       MACSTR " TA=" MACSTR " DA=" MACSTR " SA="
 			       MACSTR ")\n",
@@ -2158,9 +2093,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr3, ETH_ALEN);
 
-		if (sdata->type != IEEE80211_IF_TYPE_STA ||
-		    memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0 ||
-		    memcmp(hdr->addr2, sdata->u.sta.bssid, ETH_ALEN) != 0) {
+		if (sdata->type != IEEE80211_IF_TYPE_STA) {
 			return TXRX_DROP;
 		}
 		break;
@@ -2169,8 +2102,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
 
-		if (sdata->type != IEEE80211_IF_TYPE_IBSS ||
-		    memcmp(hdr->addr3, sdata->u.sta.bssid, ETH_ALEN) != 0) {
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
 				       MACSTR " SA=" MACSTR " BSSID=" MACSTR
@@ -2802,12 +2734,15 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		return TXRX_DROP;
 	}
 
-	/* Filter out foreign unicast packets when in promiscuous mode.
-	 * FIX: Filter out multicast to foreign BSSID. */
-	if (rx->sdata->type == IEEE80211_IF_TYPE_STA &&
-	    !MULTICAST_ADDR(hdr->addr1) &&
-	    memcmp(rx->dev->dev_addr, hdr->addr1, ETH_ALEN) != 0)
-		return TXRX_DROP;
+	if (memcmp(rx->dev->dev_addr, hdr->addr1, ETH_ALEN) == 0)
+		rx->skb->pkt_type = PACKET_HOST;
+	else if (is_multicast_ether_addr(hdr->addr1)) {
+		if (is_broadcast_ether_addr(hdr->addr1))
+			rx->skb->pkt_type = PACKET_BROADCAST;
+		else
+			rx->skb->pkt_type = PACKET_MULTICAST;
+	} else
+		rx->skb->pkt_type = PACKET_OTHERHOST;
 
 	/* Drop disallowed frame classes based on STA auth/assoc state;
 	 * IEEE 802.11, Chap 5.5.
@@ -2840,17 +2775,6 @@ ieee80211_rx_h_check(struct ieee80211_tx
 	if (rx->sta && rx->sta->key && always_sta_key) {
 		rx->key = rx->sta->key;
         } else {
-		if (!rx->sdata) {
-			printk(KERN_DEBUG "%s: sdata was null in packet!!\n",
-			       rx->dev->name);
-			printk(KERN_DEBUG "%s: Addr1: " MACSTR "\n",
-			       rx->dev->name, MAC2STR(hdr->addr1));
-			printk(KERN_DEBUG "%s: Addr2: " MACSTR "\n",
-			       rx->dev->name, MAC2STR(hdr->addr2));
-			printk(KERN_DEBUG "%s: Addr3: " MACSTR "\n",
-			       rx->dev->name, MAC2STR(hdr->addr3));
-			return TXRX_DROP;
-		}
 		if (rx->sta && rx->sta->key)
 			rx->key = rx->sta->key;
 		else
@@ -3158,41 +3082,6 @@ static u8 * ieee80211_get_bssid(struct i
 	return NULL;
 }
 
-
-static struct net_device * ieee80211_get_rx_dev(struct ieee80211_local *local,
-						struct ieee80211_hdr *hdr,
-						size_t len, int *sta_broadcast)
-{
-	u8 *bssid;
-	struct net_device *dev;
-	u16 fc;
-
-	bssid = ieee80211_get_bssid(hdr, len);
-	if (bssid) {
-		dev = ieee80211_own_bssid(local, bssid);
-		if (!dev)
-			dev = ieee80211_sta_bssid(local, bssid, hdr->addr1,
-						  sta_broadcast);
-		if (dev)
-			return dev;
-	}
-
-	if (len >= 30) {
-		fc = le16_to_cpu(hdr->frame_control);
-		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA &&
-		    (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
-		    (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
-			dev = ieee80211_get_wds_dev(local, hdr->addr2);
-			if (dev)
-				return dev;
-		}
-	}
-
-	/* Default to default device if nothing else matches */
-	return local->wdev;
-}
-
-
 static void ieee80211_rx_michael_mic_report(struct net_device *dev,
 					    struct ieee80211_hdr *hdr,
 					    struct sta_info *sta,
@@ -3283,63 +3172,31 @@ static void ieee80211_rx_michael_mic_rep
 	rx->skb = NULL;
 }
 
-
-static void ieee80211_sta_rx_broadcast(struct ieee80211_txrx_data *rx)
+static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
+						struct ieee80211_txrx_data *rx,
+						struct sta_info *sta)
 {
-	struct ieee80211_local *local = rx->dev->priv;
-	u8 *_bssid, bssid[ETH_ALEN];
-	struct sk_buff *orig_skb = rx->skb, *skb;
-	struct ieee80211_hdr *hdr;
 	ieee80211_rx_handler *handler;
-	ieee80211_txrx_result res;
-	struct list_head *ptr;
-
-	hdr = (struct ieee80211_hdr *) orig_skb->data;
-	_bssid = ieee80211_get_bssid(hdr, orig_skb->len);
-	if (_bssid == NULL) {
-		dev_kfree_skb(orig_skb);
-		return;
-	}
-	memcpy(bssid, _bssid, ETH_ALEN);
-
-	list_for_each(ptr, &local->sub_if_list) {
-		struct ieee80211_sub_if_data *sdata =
-			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		if (sdata->type != IEEE80211_IF_TYPE_STA ||
-		    (memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) != 0 &&
-		     !(bssid[0] & 0x01)))
-			continue;
+        ieee80211_txrx_result res = TXRX_DROP;
 
-		skb = skb_copy(orig_skb, GFP_ATOMIC);
-		if (skb == NULL) {
-			if (net_ratelimit()) {
-				printk(KERN_DEBUG "%s: failed to copy "
-				       "multicast frame for %s",
-				       rx->dev->name, sdata->dev->name);
+	for (handler = local->rx_handlers; *handler != NULL; handler++) {
+		res = (*handler)(rx);
+		if (res != TXRX_CONTINUE) {
+			if (res == TXRX_DROP) {
+				I802_DEBUG_INC(local->rx_handlers_drop);
+				if (sta)
+					sta->rx_dropped++;
 			}
-			continue;
-		}
-
-		hdr = (struct ieee80211_hdr *) skb->data;
-		rx->skb = skb;
-		rx->dev = sdata->dev;
-		rx->sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
-
-		res = TXRX_DROP;
-		for (handler = local->rx_handlers; *handler != NULL; handler++)
-		{
-			res = (*handler)(rx);
-			if (res == TXRX_DROP || res == TXRX_QUEUED)
-				break;
+			if (res == TXRX_QUEUED)
+				I802_DEBUG_INC(local->rx_handlers_queued);
+			break;
 		}
-
-		if (res == TXRX_DROP || *handler == NULL)
-			dev_kfree_skb(skb);
 	}
 
-	dev_kfree_skb(orig_skb);
-}
 
+	if (res == TXRX_DROP || *handler == NULL)
+		dev_kfree_skb(rx->skb);
+}
 
 /*
  * This is the receive path handler. It is called by a low level driver when an
@@ -3349,71 +3206,118 @@ void __ieee80211_rx(struct net_device *d
 		    struct ieee80211_rx_status *status)
 {
 	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
 	struct ieee80211_hdr *hdr;
-	ieee80211_rx_handler *handler;
 	struct ieee80211_txrx_data rx;
-        ieee80211_txrx_result res = TXRX_DROP;
 	u16 type;
-	int sta_broadcast = 0;
+	int multicast;
 
 	hdr = (struct ieee80211_hdr *) skb->data;
 	memset(&rx, 0, sizeof(rx));
 	rx.skb = skb;
 	rx.local = local;
-	if (skb->len >= 16)
-		sta = rx.sta = sta_info_get(local, hdr->addr2);
-	else
-		sta = rx.sta = NULL;
-	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS)) {
-		rx.dev = sta->dev;
-		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
-	} else {
-		rx.dev = ieee80211_get_rx_dev(local, hdr, skb->len,
-					      &sta_broadcast);
-		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
-		if (sta == NULL &&
-		    rx.sdata->type == IEEE80211_IF_TYPE_IBSS) {
-			u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
-			if (bssid)
-				sta = rx.sta =
-					ieee80211_ibss_add_sta(dev, skb, bssid,
-							       hdr->addr2);
-		}
-	}
 
 	rx.u.rx.status = status;
 	rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0;
 	type = WLAN_FC_GET_TYPE(rx.fc);
 	if (type == WLAN_FC_TYPE_DATA || type == WLAN_FC_TYPE_MGMT)
 		local->dot11ReceivedFragmentCount++;
-	if (sta_broadcast) {
-		ieee80211_sta_rx_broadcast(&rx);
-		goto end;
-	}
+	multicast = is_multicast_ether_addr(hdr->addr1);
+
+	if (skb->len >= 16)
+		sta = rx.sta = sta_info_get(local, hdr->addr2);
+	else
+		sta = rx.sta = NULL;
 
         if ((status->flag & RX_FLAG_MMIC_ERROR)) {
 		ieee80211_rx_michael_mic_report(dev, hdr, sta, &rx);
 		goto end;
         }
 
-	for (handler = local->rx_handlers; *handler != NULL; handler++) {
-		res = (*handler)(&rx);
-		if (res != TXRX_CONTINUE) {
-			if (res == TXRX_DROP) {
-				I802_DEBUG_INC(local->rx_handlers_drop);
-				if (sta)
-					sta->rx_dropped++;
+	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
+	    !local->iff_promiscs && !multicast) {
+		rx.dev = sta->dev;
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+		ieee80211_invoke_rx_handlers(local, &rx, sta);
+	} else {
+		struct ieee80211_sub_if_data *prev = NULL;
+		struct sk_buff *skb_new;
+		u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
+
+		list_for_each_entry(sdata, &local->sub_if_list, list) {
+			switch (sdata->type) {
+			case IEEE80211_IF_TYPE_STA:
+				if (!bssid || memcmp(sdata->u.sta.bssid,
+						     bssid, ETH_ALEN) != 0)
+					continue;
+				if (!multicast && !sdata->promisc &&
+				    memcmp(sdata->dev->dev_addr, hdr->addr1,
+					   ETH_ALEN) != 0)
+					continue;
+				break;
+			case IEEE80211_IF_TYPE_IBSS:
+				if (!bssid ||
+				    !ieee80211_bssid_match(bssid,
+							   sdata->u.sta.bssid))
+					continue;
+				if (!multicast && !sdata->promisc &&
+				    memcmp(sdata->dev->dev_addr, hdr->addr1,
+					   ETH_ALEN) != 0)
+					continue;
+				if (sta == NULL) {
+					sta = rx.sta =
+						ieee80211_ibss_add_sta(dev, skb, bssid,
+								       hdr->addr2);
+						/* FIXME: call with sdata->dev */
+				}
+				break;
+			case IEEE80211_IF_TYPE_AP:
+				if (!bssid) {
+					if (memcmp(sdata->dev->dev_addr,
+						   hdr->addr1, ETH_ALEN) != 0)
+						continue;
+				} else if (!local->sta_scanning &&
+					   !local->scan.in_scan &&
+					   !ieee80211_bssid_match(bssid,
+							sdata->dev->dev_addr))
+					continue;
+				break;
+			case IEEE80211_IF_TYPE_WDS:
+				if (bssid ||
+				    WLAN_FC_GET_TYPE(rx.fc) != WLAN_FC_TYPE_DATA)
+					continue;
+				if (memcmp(sdata->u.wds.remote_addr,
+					   hdr->addr2, ETH_ALEN) != 0)
+					continue;
+				break;
 			}
-			if (res == TXRX_QUEUED)
-				I802_DEBUG_INC(local->rx_handlers_queued);
-			break;
+
+			if (prev) {
+				skb_new = skb_copy(skb, GFP_ATOMIC);
+				if (skb_new == NULL) {
+					if (net_ratelimit()) {
+						printk(KERN_DEBUG "%s: failed to copy "
+						       "multicast frame for %s",
+						       dev->name, prev->dev->name);
+					}
+					continue;
+				}
+				rx.skb = skb_new;
+				rx.dev = prev->dev;
+				rx.sdata = prev;
+				ieee80211_invoke_rx_handlers(local, &rx, sta);
+			}
+			prev = sdata;
 		}
+		if (prev) {
+			rx.skb = skb;
+			rx.dev = prev->dev;
+			rx.sdata = prev;
+			ieee80211_invoke_rx_handlers(local, &rx, sta);
+		} else
+			dev_kfree_skb(skb);
 	}
-	skb = rx.skb; /* handlers are allowed to change skb */
-
-	if (res == TXRX_DROP || *handler == NULL)
-		dev_kfree_skb(skb);
 
   end:
 	if (sta)
-- 
1.3.0


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

* [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (14 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 15/17] d80211: fix handling of received frames Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:29   ` Johannes Berg
  2006-04-21 20:11 ` [PATCH 17/17] d80211: fix AP interfaces Jiri Benc
  2006-04-21 20:52 ` [PATCH 0/17] d80211 patches Michael Buesch
  17 siblings, 1 reply; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

This patch allows monitor interfaces to be set by SIOCSIWMODE and to receive
frames.

Also, "soft" and "hard" monitor modes are introduced.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/net/d80211.h         |   10 ++++++
 net/d80211/ieee80211.c       |   67 ++++++++++++++++++++++++++++++++++++++++--
 net/d80211/ieee80211_i.h     |    1 +
 net/d80211/ieee80211_iface.c |    7 ++++
 4 files changed, 81 insertions(+), 4 deletions(-)

738241025b5e0091237d8c9d809d9affbdfaee29
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 7bc66b5..23bcbfa 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -330,6 +330,8 @@ enum ieee80211_if_types {
  * @if_id: internal interface ID. This number has no particular meaning to
  *	drivers and the only allowed usage is to pass it to
  *	ieee80211_beacon_get() and ieee80211_get_buffered_bc() functions.
+ *	This field is not valid for monitor interfaces
+ *	(interfaces of %IEEE80211_IF_TYPE_MNTR type).
  * @type: one of &enum ieee80211_if_types constants. Determines the type of
  *	added/removed interface.
  * @mac_addr: pointer to MAC address of the interface. This pointer is valid
@@ -476,6 +478,10 @@ struct ieee80211_hw {
 	 */
 	unsigned int device_strips_mic:1;
 
+	/* Device is capable of performing full monitor mode even during
+	 * normal operation. */
+	unsigned int monitor_during_oper:1;
+
 	/* 1 = low-level driver supports skb fraglist (NETIF_F_FRAGLIST), i.e.,
 	 * more than one skb per frame */
 	unsigned int fraglist;
@@ -511,7 +517,9 @@ struct ieee80211_hw {
 	 * more exactly, set UP). If the handler returns zero, the interface
 	 * is added. Driver should perform any initialization it needs prior
 	 * to returning zero. By returning non-zero, adding of the interface
-	 * is not permitted. The open() handler is called after
+	 * is not permitted. Unless monitor_during_oper is set, it is
+	 * guaranteed that monitor interfaces and normal interfaces are
+	 * mutually exclusive. The open() handler is called after
 	 * add_interface() if this is the first device added. At least one
 	 * of open() and add_interface() handler has to be non-NULL. If
 	 * add_interface() is NULL, one STA interface is permitted only. */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e2a42af..b199b9e 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1891,7 +1891,9 @@ static struct net_device_stats *ieee8021
 
 static inline int identical_mac_addr_allowed(int type1, int type2)
 {
-	return ((type1 == IEEE80211_IF_TYPE_AP &&
+	return (type1 == IEEE80211_IF_TYPE_MNTR ||
+		type2 == IEEE80211_IF_TYPE_MNTR ||
+		(type1 == IEEE80211_IF_TYPE_AP &&
 		 type2 == IEEE80211_IF_TYPE_WDS) ||
 		(type1 == IEEE80211_IF_TYPE_WDS &&
 		 (type2 == IEEE80211_IF_TYPE_WDS ||
@@ -1925,6 +1927,36 @@ static int ieee80211_master_stop(struct 
 	return 0;
 }
 
+/* Check if running monitor interfaces should go to a "soft monitor" mode
+ * and switch them if necessary. */
+static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local)
+{
+	struct ieee80211_if_init_conf conf;
+
+	if (local->open_count && local->open_count == local->monitors &&
+	    !local->hw->monitor_during_oper && local->hw->remove_interface) {
+		conf.if_id = -1;
+		conf.type = IEEE80211_IF_TYPE_MNTR;
+		conf.mac_addr = NULL;
+		local->hw->remove_interface(local->mdev, &conf);
+	}
+}
+
+/* Check if running monitor interfaces should go to a "hard monitor" mode
+ * and switch them if necessary. */
+static void ieee80211_start_hard_monitor(struct ieee80211_local *local)
+{
+	struct ieee80211_if_init_conf conf;
+
+	if (local->open_count && local->open_count == local->monitors &&
+	    !local->hw->monitor_during_oper && local->hw->add_interface) {
+		conf.if_id = -1;
+		conf.type = IEEE80211_IF_TYPE_MNTR;
+		conf.mac_addr = NULL;
+		local->hw->add_interface(local->mdev, &conf);
+	}
+}
+
 static int ieee80211_open(struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata, *nsdata;
@@ -1948,13 +1980,25 @@ static int ieee80211_open(struct net_dev
 	    memcmp(sdata->u.wds.remote_addr, "\0\0\0\0\0\0", ETH_ALEN) == 0)
 		return -ENOLINK;
 
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR && local->open_count &&
+	    !local->hw->monitor_during_oper) {
+		/* run the interface in a "soft monitor" mode */
+		local->monitors++;
+		local->open_count++;
+		return 0;
+	}
+	ieee80211_start_soft_monitor(local);
+
 	if (local->hw->add_interface) {
 		conf.if_id = dev->ifindex;
 		conf.type = sdata->type;
 		conf.mac_addr = dev->dev_addr;
 		res = local->hw->add_interface(sdata->master, &conf);
-		if (res)
+		if (res) {
+			if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+				ieee80211_start_hard_monitor(local);
 			return res;
+		}
 	} else {
 		if (sdata->type != IEEE80211_IF_TYPE_STA)
 			return -EOPNOTSUPP;
@@ -1980,6 +2024,9 @@ static int ieee80211_open(struct net_dev
 	}
         local->open_count++;
 
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+		local->monitors++;
+
 	netif_start_queue(dev);
 	return 0;
 }
@@ -1992,8 +2039,19 @@ static int ieee80211_stop(struct net_dev
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR &&
+	    local->open_count > 1 && !local->hw->monitor_during_oper) {
+		/* remove "soft monitor" interface */
+		local->open_count--;
+		local->monitors--;
+		return 0;
+	}
+
         netif_stop_queue(dev);
 
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+		local->monitors--;
+
 	local->open_count--;
         if (local->open_count == 0) {
 		ieee80211_stop_scan(sdata->master);
@@ -2010,6 +2068,8 @@ static int ieee80211_stop(struct net_dev
 		local->hw->remove_interface(sdata->master, &conf);
 	}
 
+	ieee80211_start_hard_monitor(local);
+
 	return 0;
 }
 
@@ -2242,7 +2302,8 @@ ieee80211_rx_mgmt(struct net_device *dev
         size_t hlen;
         struct ieee80211_sub_if_data *sdata;
 
-        dev = local->apdev;
+	if (msg_type != ieee80211_msg_monitor)
+		dev = local->apdev;
         skb->dev = dev;
 
         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 37d533d..2dbb132 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -305,6 +305,7 @@ struct ieee80211_local {
         struct net_device *wdev; /* wlan# - default Ethernet (data) devide */
 	struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
 	int open_count;
+	int monitors;
 	struct ieee80211_conf conf;
 
 	int dev_index;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 2151bd9..dd809c2 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
+#include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <net/d80211.h>
@@ -124,6 +125,9 @@ void ieee80211_if_set_type(struct net_de
 		sdata->bss = &msdata->u.ap;
 		break;
 	}
+	case IEEE80211_IF_TYPE_MNTR:
+		dev->type = ARPHRD_IEEE80211_PRISM;
+		break;
 	default:
 		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
 		       dev->name, __FUNCTION__, type);
@@ -211,6 +215,9 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		}
 
 		break;
+	case IEEE80211_IF_TYPE_MNTR:
+		dev->type = ARPHRD_ETHER;
+		break;
 	}
 
 	/* remove all STAs that are bound to this virtual interface */
-- 
1.3.0


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

* [PATCH 17/17] d80211: fix AP interfaces
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (15 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 16/17] d80211: fix monitor interfaces Jiri Benc
@ 2006-04-21 20:11 ` Jiri Benc
  2006-04-21 20:52 ` [PATCH 0/17] d80211 patches Michael Buesch
  17 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:11 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

This allows interfaces of IEEE80211_IF_TYPE_MGMT type (wlan%dap interfaces)
to be put UP.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

906a789aa674216a18ad5dc13c0635bc5664b793
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index b199b9e..64cc66f 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1893,6 +1893,8 @@ static inline int identical_mac_addr_all
 {
 	return (type1 == IEEE80211_IF_TYPE_MNTR ||
 		type2 == IEEE80211_IF_TYPE_MNTR ||
+		type1 == IEEE80211_IF_TYPE_MGMT ||
+		type2 == IEEE80211_IF_TYPE_MGMT ||
 		(type1 == IEEE80211_IF_TYPE_AP &&
 		 type2 == IEEE80211_IF_TYPE_WDS) ||
 		(type1 == IEEE80211_IF_TYPE_WDS &&
-- 
1.3.0


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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 20:11 ` [PATCH 16/17] d80211: fix monitor interfaces Jiri Benc
@ 2006-04-21 20:29   ` Johannes Berg
  2006-04-21 20:49     ` Jiri Benc
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2006-04-21 20:29 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev, John W. Linville

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

On Fri, 2006-04-21 at 22:11 +0200, Jiri Benc wrote:

> Also, "soft" and "hard" monitor modes are introduced.

What's the distinction? The code might want some comments about what
that

> +       /* Device is capable of performing full monitor mode even during
> +        * normal operation. */

actually means. I suppose it means that the device will receive control
frames too, but I don't know if that's right.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 20:29   ` Johannes Berg
@ 2006-04-21 20:49     ` Jiri Benc
  2006-04-21 20:52       ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:49 UTC (permalink / raw)
  To: Johannes Berg; +Cc: netdev, John W. Linville

On Fri, 21 Apr 2006 22:29:29 +0200, Johannes Berg wrote:
> On Fri, 2006-04-21 at 22:11 +0200, Jiri Benc wrote:
> 
> > Also, "soft" and "hard" monitor modes are introduced.
> 
> What's the distinction? The code might want some comments about what
> that
> 
> > +       /* Device is capable of performing full monitor mode even during
> > +        * normal operation. */
> 
> actually means. I suppose it means that the device will receive control
> frames too, but I don't know if that's right.

Some devices need to be switched to completely different mode to be able
to receive all frames (including control ones) or even load another
firmware. Such devices are not capable to transmit anything while in
monitor mode and their drivers won't set monitor_during_oper.

Another devices are capable to receive all frames while continuing their
normal operation. Driver will probably set monitor_during_oper in that
case.

"Hard" monitor mode means the card is operating in a true rfmon mode -
i.e. you get everything on the given channel. "Soft" monitor mode means
that you will get only frames the device is willing to give you at the
time - this probably means only frames belonging to your BSS in case of
fullmac cards.

So, you can always do

echo -n sta0 > /sys/class/ieee80211/wiphy0/add_iface
echo -n mon0 > /sys/class/ieee80211/wiphy0/add_iface
iwconfig sta0 mode managed
iwconfig mon0 mode monitor
ifconfig sta0 up
ifconfig mon0 up

and this will work - independently of the value of monitor_during_oper.
The difference is that in case of monitor_during_oper == 0, you won't
probably receive much more frames from mon0 than from sta0. But - you
will most likely receive beacons on mon0 and also monitoring headers
(prism2 headers presently).

When monitor_during_oper == 1, you are able to watch all traffic on the
current channel on mon0 without interrupting normal functionality.

-- 
Jiri Benc
SUSE Labs

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

* Re: [PATCH 0/17] d80211 patches
  2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
                   ` (16 preceding siblings ...)
  2006-04-21 20:11 ` [PATCH 17/17] d80211: fix AP interfaces Jiri Benc
@ 2006-04-21 20:52 ` Michael Buesch
  2006-04-21 20:52   ` Jiri Benc
  17 siblings, 1 reply; 31+ messages in thread
From: Michael Buesch @ 2006-04-21 20:52 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev, John W. Linville

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

On Friday 21 April 2006 22:11, you wrote:
> Please note that these changes break d80211 drivers.

Can you please send your hacky patch for the bcm43xx
to me, so I can come up with a clean one?
(I think you already sent it to me, but I lost it :) )
Thanks.

-- 
Greetings Michael.

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

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

* Re: [PATCH 0/17] d80211 patches
  2006-04-21 20:52 ` [PATCH 0/17] d80211 patches Michael Buesch
@ 2006-04-21 20:52   ` Jiri Benc
  2006-04-26 19:39     ` John W. Linville
  0 siblings, 1 reply; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:52 UTC (permalink / raw)
  To: Michael Buesch; +Cc: netdev

On Fri, 21 Apr 2006 22:52:08 +0200, Michael Buesch wrote:
> Can you please send your hacky patch for the bcm43xx
> to me, so I can come up with a clean one?

Sure, actually I planned to do it in a few minutes :-)


 drivers/net/wireless/bcm43xx-d80211/bcm43xx.h      |    1 
 drivers/net/wireless/bcm43xx-d80211/bcm43xx_main.c |   45 +++++++++++++++++++--
 2 files changed, 42 insertions(+), 4 deletions(-)

--- dscape.orig/drivers/net/wireless/bcm43xx-d80211/bcm43xx.h
+++ dscape/drivers/net/wireless/bcm43xx-d80211/bcm43xx.h
@@ -721,6 +721,7 @@ struct bcm43xx_private {
 	/* Informational stuff. */
 	char nick[IW_ESSID_MAX_SIZE + 1];
 	u8 bssid[ETH_ALEN];
+	int interfaces;
 
 	/* encryption/decryption */
 	u16 security_offset;
--- dscape.orig/drivers/net/wireless/bcm43xx-d80211/bcm43xx_main.c
+++ dscape/drivers/net/wireless/bcm43xx-d80211/bcm43xx_main.c
@@ -4029,9 +4029,6 @@ static int bcm43xx_net_config(struct net
 	if (conf->channel != radio->channel)
 		bcm43xx_radio_selectchannel(bcm, conf->channel, 0);
 
-	if (conf->mode != bcm->iw_mode)
-		bcm43xx_set_iwmode(bcm, conf->mode);
-
 	if (conf->short_slot_time != bcm->short_slot) {
 		assert(phy->type == BCM43xx_PHYTYPE_G);
 		if (conf->short_slot_time)
@@ -4186,8 +4183,13 @@ static void bcm43xx_net_poll_controller(
 static int bcm43xx_net_open(struct net_device *net_dev)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int res;
 
-	return bcm43xx_init_board(bcm);
+	res = bcm43xx_init_board(bcm);
+	if (!res)
+		return res;
+	bcm43xx_set_iwmode(bcm, bcm->iw_mode);
+	return 0;
 }
 
 static int bcm43xx_net_stop(struct net_device *net_dev)
@@ -4202,6 +4204,39 @@ static int bcm43xx_net_stop(struct net_d
 	return 0;
 }
 
+static int bcm43xx_add_interface(struct net_device *net_dev,
+				 struct ieee80211_if_init_conf *conf)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+	if (bcm->interfaces > 0)
+		return -ENOBUFS;
+	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
+		bcm->iw_mode = IW_MODE_MONITOR;
+	} else {
+		if (memcmp(bcm->net_dev->dev_addr, conf->mac_addr, ETH_ALEN) != 0)
+			return -EADDRNOTAVAIL;
+		if (conf->type == IEEE80211_IF_TYPE_STA)
+			bcm->iw_mode = IW_MODE_INFRA;
+		else if (conf->type == IEEE80211_IF_TYPE_IBSS)
+			bcm->iw_mode = IW_MODE_ADHOC;
+		else if (conf->type == IEEE80211_IF_TYPE_AP)
+			bcm->iw_mode = IW_MODE_MASTER;
+		else
+			return -EOPNOTSUPP;
+	}
+	bcm->interfaces++;
+	return 0;
+}
+
+static void bcm43xx_remove_interface(struct net_device *net_dev,
+				     struct ieee80211_if_init_conf *conf)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+	bcm->interfaces--;
+}
+
 /* Initialization of struct net_device, just after allocation. */
 static void bcm43xx_netdev_setup(struct net_device *net_dev)
 {
@@ -4276,6 +4311,8 @@ static int __devinit bcm43xx_init_one(st
 	ieee->tx = bcm43xx_net_hard_start_xmit;
 	ieee->open = bcm43xx_net_open;
 	ieee->stop = bcm43xx_net_stop;
+	ieee->add_interface = bcm43xx_add_interface;
+	ieee->remove_interface = bcm43xx_remove_interface;
 	ieee->reset = bcm43xx_net_reset;
 	ieee->config = bcm43xx_net_config;
 //TODO	ieee->set_key = bcm43xx_net_set_key;




-- 
Jiri Benc
SUSE Labs

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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 20:49     ` Jiri Benc
@ 2006-04-21 20:52       ` Johannes Berg
  2006-04-21 20:57         ` Jiri Benc
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2006-04-21 20:52 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev, John W. Linville

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

On Fri, 2006-04-21 at 22:49 +0200, Jiri Benc wrote:
> 
> "Hard" monitor mode means the card is operating in a true rfmon mode -
> i.e. you get everything on the given channel. "Soft" monitor mode means
> that you will get only frames the device is willing to give you at the
> time - this probably means only frames belonging to your BSS in case of
> fullmac cards. 

Ok, thanks for clarifying; this description should be somewhere in the
comments or so IMHO.

> and this will work - independently of the value of monitor_during_oper.
> The difference is that in case of monitor_during_oper == 0, you won't
> probably receive much more frames from mon0 than from sta0. But - you
> will most likely receive beacons on mon0 and also monitoring headers
> (prism2 headers presently).

This I don't understand, doesn't the UI kind of suck as opposed to just
putting the sta0 device into promisc mode?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 20:52       ` Johannes Berg
@ 2006-04-21 20:57         ` Jiri Benc
  2006-04-21 21:01           ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 20:57 UTC (permalink / raw)
  To: Johannes Berg; +Cc: netdev, John W. Linville

On Fri, 21 Apr 2006 22:52:58 +0200, Johannes Berg wrote:
> > and this will work - independently of the value of monitor_during_oper.
> > The difference is that in case of monitor_during_oper == 0, you won't
> > probably receive much more frames from mon0 than from sta0. But - you
> > will most likely receive beacons on mon0 and also monitoring headers
> > (prism2 headers presently).
> 
> This I don't understand, doesn't the UI kind of suck as opposed to just
> putting the sta0 device into promisc mode?

In promisc mode, you receive only packets destined to your BSS,
regardless of their source or destination address (so it's similar to
the way promisc works with Ethernet). On monitor interface, you receive
all packets regardless of BSSID.

 Jiri

-- 
Jiri Benc
SUSE Labs

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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 20:57         ` Jiri Benc
@ 2006-04-21 21:01           ` Johannes Berg
  2006-04-21 21:05             ` Jiri Benc
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2006-04-21 21:01 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev, John W. Linville

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

On Fri, 2006-04-21 at 22:57 +0200, Jiri Benc wrote:
> On Fri, 21 Apr 2006 22:52:58 +0200, Johannes Berg wrote:
> > > and this will work - independently of the value of monitor_during_oper.
> > > The difference is that in case of monitor_during_oper == 0, you won't
> > > probably receive much more frames from mon0 than from sta0. But - you
> > > will most likely receive beacons on mon0 and also monitoring headers
> > > (prism2 headers presently).
> > 
> > This I don't understand, doesn't the UI kind of suck as opposed to just
> > putting the sta0 device into promisc mode?
> 
> In promisc mode, you receive only packets destined to your BSS,
> regardless of their source or destination address (so it's similar to
> the way promisc works with Ethernet). On monitor interface, you receive
> all packets regardless of BSSID.

Yes, but didn't you just say that when monitor_during_oper == 0 then
it's equivalent to promisc mode?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 21:01           ` Johannes Berg
@ 2006-04-21 21:05             ` Jiri Benc
  2006-04-21 21:05               ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Jiri Benc @ 2006-04-21 21:05 UTC (permalink / raw)
  To: Johannes Berg; +Cc: netdev, John W. Linville

On Fri, 21 Apr 2006 23:01:28 +0200, Johannes Berg wrote:
> Yes, but didn't you just say that when monitor_during_oper == 0 then
> it's equivalent to promisc mode?

Not necessary. It was just an example of the worst case. In typical
case, you will receive something more - probably all data and management
frames but no control frames.

 Jiri

-- 
Jiri Benc
SUSE Labs

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

* Re: [PATCH 16/17] d80211: fix monitor interfaces
  2006-04-21 21:05             ` Jiri Benc
@ 2006-04-21 21:05               ` Johannes Berg
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2006-04-21 21:05 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev, John W. Linville

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

On Fri, 2006-04-21 at 23:05 +0200, Jiri Benc wrote:

> Not necessary. It was just an example of the worst case. In typical
> case, you will receive something more - probably all data and management
> frames but no control frames.

Ah right, yeah makes sense then I guess. So monitor is a way of telling
the driver "give me everything that you can" :)

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

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

* Re: [PATCH 0/17] d80211 patches
  2006-04-21 20:52   ` Jiri Benc
@ 2006-04-26 19:39     ` John W. Linville
  2006-04-26 21:27       ` Ivo van Doorn
                         ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: John W. Linville @ 2006-04-26 19:39 UTC (permalink / raw)
  To: Jiri Benc; +Cc: Michael Buesch, netdev

On Fri, Apr 21, 2006 at 10:52:10PM +0200, Jiri Benc wrote:
> On Fri, 21 Apr 2006 22:52:08 +0200, Michael Buesch wrote:
> > Can you please send your hacky patch for the bcm43xx
> > to me, so I can come up with a clean one?
> 
> Sure, actually I planned to do it in a few minutes :-)

Hacky or not, I'm applying this patch to keep the bcm43xx driver
from breaking.  I don't suppose you have a patch for the rt2x00 driver?

John
-- 
John W. Linville
linville@tuxdriver.com

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

* Re: [PATCH 0/17] d80211 patches
  2006-04-26 19:39     ` John W. Linville
@ 2006-04-26 21:27       ` Ivo van Doorn
  2006-04-27 12:49       ` Michael Buesch
  2006-04-28 15:45       ` [PATCH] bcm43xx_d80211: fix bug in open Jiri Benc
  2 siblings, 0 replies; 31+ messages in thread
From: Ivo van Doorn @ 2006-04-26 21:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: Jiri Benc, Michael Buesch, netdev

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

On Wednesday 26 April 2006 21:39, John W. Linville wrote:
> On Fri, Apr 21, 2006 at 10:52:10PM +0200, Jiri Benc wrote:
> > On Fri, 21 Apr 2006 22:52:08 +0200, Michael Buesch wrote:
> > > Can you please send your hacky patch for the bcm43xx
> > > to me, so I can come up with a clean one?
> > 
> > Sure, actually I planned to do it in a few minutes :-)
> 
> Hacky or not, I'm applying this patch to keep the bcm43xx driver
> from breaking.  I don't suppose you have a patch for the rt2x00 driver?

Hi,

I had promised to create this patch before, but due to shortage of time
hadn't managed to do so. At the moment a compatibility fix for the updates
is already present in our CVS tree.
I am already working on a patch series to send for wireless-dev to bring rt2x00
up to date. The change for compatibility for the stack is update is also amongst the
patches. I am still working on the final patches for the series, but will be able to
send all (+/- 30 patches) tomorow.

After that I hope to send new patches for rt2x00 on a more regular basis,
to prevent large patch series like this one to be send in a single day.

IvD

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

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

* Re: [PATCH 0/17] d80211 patches
  2006-04-26 19:39     ` John W. Linville
  2006-04-26 21:27       ` Ivo van Doorn
@ 2006-04-27 12:49       ` Michael Buesch
  2006-04-28 15:45       ` [PATCH] bcm43xx_d80211: fix bug in open Jiri Benc
  2 siblings, 0 replies; 31+ messages in thread
From: Michael Buesch @ 2006-04-27 12:49 UTC (permalink / raw)
  To: John W. Linville; +Cc: Jiri Benc, netdev

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

On Wednesday 26 April 2006 21:39, John W. Linville wrote:
> On Fri, Apr 21, 2006 at 10:52:10PM +0200, Jiri Benc wrote:
> > On Fri, 21 Apr 2006 22:52:08 +0200, Michael Buesch wrote:
> > > Can you please send your hacky patch for the bcm43xx
> > > to me, so I can come up with a clean one?
> > 
> > Sure, actually I planned to do it in a few minutes :-)
> 
> Hacky or not, I'm applying this patch to keep the bcm43xx driver
> from breaking.
That's perfectly fine.
The correct patch needs a little bit of rewriting in the "mode" code.
I will do that after I finished the 4318 fixes (should take quite
some time).

-- 
Greetings Michael.

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

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

* [PATCH] bcm43xx_d80211: fix bug in open
  2006-04-26 19:39     ` John W. Linville
  2006-04-26 21:27       ` Ivo van Doorn
  2006-04-27 12:49       ` Michael Buesch
@ 2006-04-28 15:45       ` Jiri Benc
  2 siblings, 0 replies; 31+ messages in thread
From: Jiri Benc @ 2006-04-28 15:45 UTC (permalink / raw)
  To: John W. Linville; +Cc: Michael Buesch, netdev

On Wed, 26 Apr 2006 15:39:12 -0400, John W. Linville wrote:
> Hacky or not, I'm applying this patch to keep the bcm43xx driver
> from breaking.  I don't suppose you have a patch for the rt2x00 driver?

The patch for bcm43xx was really just quick fix, only partially
tested...

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -4172,7 +4172,7 @@ static int bcm43xx_net_open(struct net_d
 	int res;
 
 	res = bcm43xx_init_board(bcm);
-	if (!res)
+	if (res)
 		return res;
 	bcm43xx_set_iwmode(bcm, bcm->iw_mode);
 	return 0;


-- 
Jiri Benc
SUSE Labs

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

end of thread, other threads:[~2006-04-28 15:45 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-04-21 20:11 [PATCH 0/17] d80211 patches Jiri Benc
2006-04-21 20:11 ` [PATCH 1/17] d80211: Replace MODULE_PARM with module_param Jiri Benc
2006-04-21 20:11 ` [PATCH 2/17] d80211: symlinks to wiphy in sysfs Jiri Benc
2006-04-21 20:11 ` [PATCH 3/17] d80211: allow WDS remote to by set by WE Jiri Benc
2006-04-21 20:11 ` [PATCH 4/17] d80211: add IBSS and monitor interface types Jiri Benc
2006-04-21 20:11 ` [PATCH 5/17] d80211: non-shared " Jiri Benc
2006-04-21 20:11 ` [PATCH 6/17] d80211: remove local->bssid variable Jiri Benc
2006-04-21 20:11 ` [PATCH 7/17] d80211: rename IEEE80211_SUB_IF_TYPE_ constants Jiri Benc
2006-04-21 20:11 ` [PATCH 8/17] d80211: ask driver for allowed iface combinations Jiri Benc
2006-04-21 20:11 ` [PATCH 9/17] d80211: remove obsolete stuff Jiri Benc
2006-04-21 20:11 ` [PATCH 10/17] d80211: fix interface configuration Jiri Benc
2006-04-21 20:11 ` [PATCH 11/17] d80211: rename adm_status to radio_enabled Jiri Benc
2006-04-21 20:11 ` [PATCH 12/17] d80211: interface types changeable by SIOCSIWMODE Jiri Benc
2006-04-21 20:11 ` [PATCH 13/17] d80211: master interface auto up/down Jiri Benc
2006-04-21 20:11 ` [PATCH 14/17] d80211: set_multicast_list Jiri Benc
2006-04-21 20:11 ` [PATCH 15/17] d80211: fix handling of received frames Jiri Benc
2006-04-21 20:11 ` [PATCH 16/17] d80211: fix monitor interfaces Jiri Benc
2006-04-21 20:29   ` Johannes Berg
2006-04-21 20:49     ` Jiri Benc
2006-04-21 20:52       ` Johannes Berg
2006-04-21 20:57         ` Jiri Benc
2006-04-21 21:01           ` Johannes Berg
2006-04-21 21:05             ` Jiri Benc
2006-04-21 21:05               ` Johannes Berg
2006-04-21 20:11 ` [PATCH 17/17] d80211: fix AP interfaces Jiri Benc
2006-04-21 20:52 ` [PATCH 0/17] d80211 patches Michael Buesch
2006-04-21 20:52   ` Jiri Benc
2006-04-26 19:39     ` John W. Linville
2006-04-26 21:27       ` Ivo van Doorn
2006-04-27 12:49       ` Michael Buesch
2006-04-28 15:45       ` [PATCH] bcm43xx_d80211: fix bug in open Jiri Benc

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.