netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Benc <jbenc@suse.cz>
To: netdev@vger.kernel.org
Cc: "John W. Linville" <linville@tuxdriver.com>
Subject: [PATCH 10/17] d80211: fix interface configuration
Date: Fri, 21 Apr 2006 22:11:41 +0200 (CEST)	[thread overview]
Message-ID: <20060421201141.8DAD7482CA@silver.suse.cz> (raw)
In-Reply-To: <20060421220951.205579000.midnight@suse.cz>

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


  parent reply	other threads:[~2006-04-21 20:11 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Jiri Benc [this message]
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

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20060421201141.8DAD7482CA@silver.suse.cz \
    --to=jbenc@suse.cz \
    --cc=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).