From patchwork Mon Nov 2 21:42:44 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Chamberlain X-Patchwork-Id: 57138 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nA2LhP8t004846 for ; Mon, 2 Nov 2009 21:43:26 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756874AbZKBVmn (ORCPT ); Mon, 2 Nov 2009 16:42:43 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756600AbZKBVmm (ORCPT ); Mon, 2 Nov 2009 16:42:42 -0500 Received: from bombadil.infradead.org ([18.85.46.34]:45627 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756861AbZKBVmk (ORCPT ); Mon, 2 Nov 2009 16:42:40 -0500 Received: from mcgrof by bombadil.infradead.org with local (Exim 4.69 #1 (Red Hat Linux)) id 1N54fk-0003SQ-Jh; Mon, 02 Nov 2009 21:42:44 +0000 Date: Mon, 2 Nov 2009 16:42:44 -0500 From: "Luis R. Rodriguez" To: "Luis R. Rodriguez" Cc: Johannes Berg , linux-wireless , Jouni Malinen , Sujith Manoharan , Vasanthakumar Thiagarajan , Senthil Balasubramanian Subject: Re: [RFC] mac80211: make ieee80211_find_sta per virtual interface Message-ID: <20091102214244.GA25479@bombadil.infradead.org> References: <1256896722.3555.39.camel@johannes.local> <43e72e890910300802v25ba6211s4e9302dd1968230e@mail.gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <43e72e890910300802v25ba6211s4e9302dd1968230e@mail.gmail.com> User-Agent: Mutt/1.5.19 (2009-01-05) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 330cd3b..9c41071 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -17,23 +17,29 @@ #include "ath9k.h" static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, - struct ieee80211_hdr *hdr) + struct ieee80211_hdr *hdr, + struct ieee80211_vif **vif) { struct ieee80211_hw *hw = sc->pri_wiphy->hw; int i; + *vif = ieee80211_get_vif_by_mac_atomic(hw, hdr->addr1); + if (*vif) + return hw; + spin_lock_bh(&sc->wiphy_lock); for (i = 0; i < sc->num_sec_wiphy; i++) { struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) + if (!aphy) continue; - if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) - == 0) { + *vif = ieee80211_get_vif_by_mac_atomic(aphy->hw, hdr->addr1); + if (*vif) { hw = aphy->hw; break; } } spin_unlock_bh(&sc->wiphy_lock); + return hw; } @@ -662,6 +668,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) struct ieee80211_rx_status rx_status; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_vif *vif; /* * The hw can techncically differ from common->hw when using ath9k * virtual wiphy so to account for that we iterate over the active @@ -748,7 +755,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) DMA_FROM_DEVICE); hdr = (struct ieee80211_hdr *) skb->data; - hw = ath_get_virt_hw(sc, hdr); + hw = ath_get_virt_hw(sc, hdr, &vif); /* * If we're asked to flush receive queue, directly diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e12293e..1d2bb0a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1999,6 +1999,12 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, struct ieee80211_vif *vif), void *data); +struct ieee80211_vif *ieee80211_get_vif_by_mac(struct ieee80211_hw *hw, + u8 *mac); + +struct ieee80211_vif *ieee80211_get_vif_by_mac_atomic(struct ieee80211_hw *hw, + u8 *mac); + /** * ieee80211_queue_work - add work onto the mac80211 workqueue * diff --git a/net/mac80211/util.c b/net/mac80211/util.c index aedbaaa..f3f5a8b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -511,6 +511,107 @@ void ieee80211_iterate_active_interfaces_atomic( } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); +static struct ieee80211_vif *ieee80211_get_first_mon_vif(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_vif *vif = NULL; + + if (likely(!local->monitors && local->cooked_mntrs++)) + return NULL; + + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { + vif = &sdata->vif; + break; + } + } + + return vif; +} + +struct ieee80211_vif *ieee80211_get_vif_by_mac(struct ieee80211_hw *hw, + u8 *mac) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_vif *vif = NULL; + + mutex_lock(&local->iflist_mtx); + + list_for_each_entry(sdata, &local->interfaces, list) { + switch (sdata->vif.type) { + case __NL80211_IFTYPE_AFTER_LAST: + 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 (compare_ether_addr(mac, sdata->dev->dev_addr) == 0) { + vif = &sdata->vif; + break; + } + } + + if (!vif) { + vif = ieee80211_get_first_mon_vif(hw); + WARN_ON(!vif); + } + + mutex_unlock(&local->iflist_mtx); + + return vif; +} +EXPORT_SYMBOL_GPL(ieee80211_get_vif_by_mac); + +struct ieee80211_vif *ieee80211_get_vif_by_mac_atomic(struct ieee80211_hw *hw, + u8 *mac) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_vif *vif = NULL; + + rcu_read_lock(); + + list_for_each_entry(sdata, &local->interfaces, list) { + switch (sdata->vif.type) { + case __NL80211_IFTYPE_AFTER_LAST: + 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 (compare_ether_addr(mac, sdata->dev->dev_addr) == 0) { + vif = &sdata->vif; + break; + } + } + + if (!vif) { + vif = ieee80211_get_first_mon_vif(hw); + WARN_ON(!vif); + } + + rcu_read_unlock(); + + return vif; +} +EXPORT_SYMBOL_GPL(ieee80211_get_vif_by_mac_atomic); + /* * Nothing should have been stuffed into the workqueue during * the suspend->resume cycle. If this WARN is seen then there