linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ben Greear <greearb@candelatech.com>
To: "linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>,
	"ath9k-devel@lists.ath9k.org" <ath9k-devel@venema.h4ckr.net>
Subject: RFC:  v3: Support multiple STA on same AP with ath9k
Date: Fri, 10 Sep 2010 13:07:20 -0700	[thread overview]
Message-ID: <4C8A8FF8.4030900@candelatech.com> (raw)

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

The attached patch lets mac80111 create multiple STA on the same
AP, and the changes to ath9k let it function properly, at least for
un-encrypted traffic.  WPA does not work..no idea why yet.

It also consolidates some of the util.c iterator logic in
mac80211.

Please let me know if this is moving in the right direction.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



[-- Attachment #2: wt-36-vsta-ok-c.patch --]
[-- Type: text/plain, Size: 10039 bytes --]

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 2a6e45a..26fb322 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -416,6 +416,7 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv)
 
 	/* configure bssid mask */
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+		/* NOTE:  Maybe this should be ath9k_set_bssid_mask?? */
 		ath_hw_setbssidmask(common);
 
 	/* configure operational mode */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index b32c8f0..4ce4029 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -110,7 +110,6 @@ static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
 static void ath_opmode_init(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
 
 	u32 rfilt, mfilt[2];
 
@@ -118,9 +117,15 @@ static void ath_opmode_init(struct ath_softc *sc)
 	rfilt = ath_calcrxfilter(sc);
 	ath9k_hw_setrxfilter(ah, rfilt);
 
-	/* configure bssid mask */
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		ath_hw_setbssidmask(common);
+	/* configure bssid mask, if ah->hw is configured.
+	 * it is NOT configured when mac80211 is calling
+	 * ieee80211_do_open, but probably just as well since
+	 * this STA isn't in the list yet.
+	 */
+	if (ah->hw) {
+		if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+			ath9k_set_bssid_mask(ah->hw);
+	}
 
 	/* configure operational mode */
 	ath9k_hw_setopmode(ah);
@@ -426,6 +431,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 #define	RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
 
 	u32 rfilt;
+	int avifs = ieee80211_count_sta_atomic(sc->hw);
 
 	rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
 		| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
@@ -448,7 +454,11 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 	if (sc->rx.rxfilter & FIF_CONTROL)
 		rfilt |= ATH9K_RX_FILTER_CONTROL;
 
+	/* If we have more than one active STA, then we need to
+	 * accept more than just MYBEACON.
+	 */
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+	    (avifs <= 1) &&
 	    !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
 		rfilt |= ATH9K_RX_FILTER_MYBEACON;
 	else
@@ -463,9 +473,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 	if (conf_is_ht(&sc->hw->conf))
 		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
 
-	if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
-		/* TODO: only needed if more than one BSSID is in use in
-		 * station/adhoc mode */
+	if (sc->sec_wiphy || (avifs > 1) || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
 		/* The following may also be needed for other older chips */
 		if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
 			rfilt |= ATH9K_RX_FILTER_PROM;
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index fd20241..9c1d529 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -59,15 +59,17 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
 	} else
 		iter_data.count = 0;
 
-	/* Get list of all active MAC addresses */
+	/* Get list of all MAC addresses for STA and ADHOC interfaces. */
 	spin_lock_bh(&sc->wiphy_lock);
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
-						   &iter_data);
+	ieee80211_iterate_interfaces_helper(sc->hw, true, false,
+					    ath9k_vif_iter,
+					    &iter_data);
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
 		if (sc->sec_wiphy[i] == NULL)
 			continue;
-		ieee80211_iterate_active_interfaces_atomic(
-			sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
+		ieee80211_iterate_interfaces_helper(
+			sc->sec_wiphy[i]->hw, true, false,
+			ath9k_vif_iter, &iter_data);
 	}
 	spin_unlock_bh(&sc->wiphy_lock);
 
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f91fc33..e87396d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2320,6 +2320,35 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
 						    u8 *mac,
 						    struct ieee80211_vif *vif),
 						void *data);
+/**
+ * ieee80211_iterate_interfaces_helper - iterate interfaces
+ *
+ * This function iterates over the interfaces associated with a given
+ * hardware and calls the callback for them.  If do_atomic is true,
+ * this function requires the iterator callback function to be atomic,
+ * if that is not desired, set do_atomic to false.
+ * If you want only active interfaces, set active_only to true.
+ * See also: @ieee80211_iterate_active_interfaces
+ *           @ieee80211_iterate_active_interfaces_atomic
+ *
+ * Returns number of interfaces to be filtered.
+ * @hw: the hardware struct of which the interfaces should be iterated over
+ * @do_atomic:  Should iterator be treated as atomic or not.
+ * @active_only:  Should we only iterate over active interfaces.
+ * @iterator: the iterator function to call, cannot sleep
+ * @data: first argument of the iterator function
+ */
+int ieee80211_iterate_interfaces_helper(struct ieee80211_hw *hw,
+					bool do_atomic,
+					bool active_only,
+					void (*iterator)(void *data, u8 *mac,
+						struct ieee80211_vif *vif),
+					void *data);
+
+/** Return a count of all station-like interfaces for
+ * this hardware.  Running/Stopped state has no affect.
+ */
+int ieee80211_count_sta_atomic(struct ieee80211_hw *hw);
 
 /**
  * ieee80211_queue_work - add work onto the mac80211 workqueue
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 687077e..db751f1 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -440,7 +440,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
 
 	spin_lock_irqsave(&local->sta_lock, flags);
 	/* check if STA exists already */
-	if (sta_info_get_bss(sdata, sta->sta.addr)) {
+	if (sta_info_get(sdata, sta->sta.addr)) {
 		spin_unlock_irqrestore(&local->sta_lock, flags);
 		mutex_unlock(&local->sta_mtx);
 		rcu_read_lock();
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index bd40b11..1096dac 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -461,37 +461,75 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_wake_queues);
 
-void ieee80211_iterate_active_interfaces(
+static int _iter_loop_helper(
+	struct ieee80211_sub_if_data *sdata,
+	bool active_only,
+	void (*iterator)(void *data, u8 *mac,
+			 struct ieee80211_vif *vif),
+	void *data)
+{
+	switch (sdata->vif.type) {
+	case NUM_NL80211_IFTYPES:
+	case NL80211_IFTYPE_UNSPECIFIED:
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_AP_VLAN:
+		return 0;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_MESH_POINT:
+		break;
+	}
+	if (ieee80211_sdata_running(sdata) || !active_only) {
+		if (iterator)
+			iterator(data, sdata->vif.addr,
+				 &sdata->vif);
+		return 1;
+	}
+	return 0;
+}
+
+int ieee80211_iterate_interfaces_helper(
 	struct ieee80211_hw *hw,
+	bool do_atomic,
+	bool active_only,
 	void (*iterator)(void *data, u8 *mac,
 			 struct ieee80211_vif *vif),
 	void *data)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_sub_if_data *sdata;
+	int cnt = 0;
 
-	mutex_lock(&local->iflist_mtx);
+	if (do_atomic) {
+		rcu_read_lock();
 
-	list_for_each_entry(sdata, &local->interfaces, list) {
-		switch (sdata->vif.type) {
-		case NUM_NL80211_IFTYPES:
-		case NL80211_IFTYPE_UNSPECIFIED:
-		case NL80211_IFTYPE_MONITOR:
-		case NL80211_IFTYPE_AP_VLAN:
-			continue;
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_WDS:
-		case NL80211_IFTYPE_MESH_POINT:
-			break;
+		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+			cnt += _iter_loop_helper(sdata, active_only,
+						 iterator, data);
 		}
-		if (ieee80211_sdata_running(sdata))
-			iterator(data, sdata->vif.addr,
-				 &sdata->vif);
+		rcu_read_unlock();
+	} else {
+		mutex_lock(&local->iflist_mtx);
+		list_for_each_entry(sdata, &local->interfaces, list) {
+			cnt += _iter_loop_helper(sdata, active_only,
+						 iterator, data);
+		}
+		mutex_unlock(&local->iflist_mtx);
 	}
+	return cnt;
+}
+EXPORT_SYMBOL_GPL(ieee80211_iterate_interfaces_helper);
+
 
-	mutex_unlock(&local->iflist_mtx);
+void ieee80211_iterate_active_interfaces(
+	struct ieee80211_hw *hw,
+	void (*iterator)(void *data, u8 *mac,
+			 struct ieee80211_vif *vif),
+	void *data)
+{
+	ieee80211_iterate_interfaces_helper(hw, false, false, iterator, data);
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
 
@@ -501,33 +539,20 @@ void ieee80211_iterate_active_interfaces_atomic(
 			 struct ieee80211_vif *vif),
 	void *data)
 {
-	struct ieee80211_local *local = hw_to_local(hw);
-	struct ieee80211_sub_if_data *sdata;
+	ieee80211_iterate_interfaces_helper(hw, true, false, iterator, data);
+}
+EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
 
-	rcu_read_lock();
 
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		switch (sdata->vif.type) {
-		case NUM_NL80211_IFTYPES:
-		case NL80211_IFTYPE_UNSPECIFIED:
-		case NL80211_IFTYPE_MONITOR:
-		case NL80211_IFTYPE_AP_VLAN:
-			continue;
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_WDS:
-		case NL80211_IFTYPE_MESH_POINT:
-			break;
-		}
-		if (ieee80211_sdata_running(sdata))
-			iterator(data, sdata->vif.addr,
-				 &sdata->vif);
-	}
 
-	rcu_read_unlock();
+/** Return a count of all station-like interfaces for
+ * this hardware.  Running/Stopped state has no affect.
+ */
+int ieee80211_count_sta_atomic(struct ieee80211_hw *hw)
+{
+	return ieee80211_iterate_interfaces_helper(hw, true, false, NULL, NULL);
 }
-EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
+EXPORT_SYMBOL_GPL(ieee80211_count_sta_atomic);
 
 /*
  * Nothing should have been stuffed into the workqueue during

             reply	other threads:[~2010-09-10 20:07 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-10 20:07 Ben Greear [this message]
2010-09-10 21:12 ` RFC: v3: Support multiple STA on same AP with ath9k Johannes Berg
2010-09-10 21:23   ` Ben Greear
2010-09-10 21:27     ` Johannes Berg
2010-09-13 12:14 ` Vasanthakumar Thiagarajan
2010-09-13 14:36   ` Ben Greear
2010-09-13 19:23   ` Ben Greear
2010-09-14 13:46     ` Vasanthakumar Thiagarajan
2010-09-14 14:39       ` Ben Greear
2010-09-14 14:44         ` Vasanthakumar Thiagarajan

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=4C8A8FF8.4030900@candelatech.com \
    --to=greearb@candelatech.com \
    --cc=ath9k-devel@venema.h4ckr.net \
    --cc=linux-wireless@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).