summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-09-24 18:29:00 +0200
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-12-01 21:17:52 +0200
commita399f98069743a9a17f85a406b4dc36c059f75ca (patch)
tree8de3e37b6aa9f9e19b85261013f4e775423922f7 /drivers/net/wireless/intel/iwlwifi/mvm/rx.c
parent04b089922412ad3d0cee0046fd0cb495ef22b8e8 (diff)
iwlwifi: mvm: use firmware station lookup, combine code
In most cases, the firmware will already match the station that we received a given frame from and tell us the station ID in the RX status, so we can look up the station from that. This lets us skip the (more expensive) hash table lookup in mac80211. Also change the fallback case (no station info from the firmware) to not attempt to look up a multicast source address. While at it, also combine all the code using the station into a single if block. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/rx.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index d1d50ffb1459..a0e957a4018d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -61,6 +61,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
+#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include "iwl-trans.h"
#include "mvm.h"
@@ -262,7 +263,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_rx_phy_info *phy_info;
struct iwl_rx_mpdu_res_start *rx_res;
- struct ieee80211_sta *sta;
+ struct ieee80211_sta *sta = NULL;
struct sk_buff *skb;
u32 len;
u32 ampdu_status;
@@ -333,22 +334,33 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
(unsigned long long)rx_status->mactime);
rcu_read_lock();
- /*
- * We have tx blocked stations (with CS bit). If we heard frames from
- * a blocked station on a new channel we can TX to it again.
- */
- if (unlikely(mvm->csa_tx_block_bcn_timeout)) {
- sta = ieee80211_find_sta(
- rcu_dereference(mvm->csa_tx_blocked_vif), hdr->addr2);
- if (sta)
- iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
+ if (rx_pkt_status & RX_MPDU_RES_STATUS_SRC_STA_FOUND) {
+ u32 id = rx_pkt_status & RX_MPDU_RES_STATUS_STA_ID_MSK;
+
+ id >>= RX_MDPU_RES_STATUS_STA_ID_SHIFT;
+
+ if (!WARN_ON_ONCE(id >= IWL_MVM_STATION_COUNT)) {
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
+ if (IS_ERR(sta))
+ sta = NULL;
+ }
+ } else if (!is_multicast_ether_addr(hdr->addr2)) {
+ /* This is fine since we prevent two stations with the same
+ * address from being added.
+ */
+ sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
}
- /* This is fine since we don't support multiple AP interfaces */
- sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ /* We have tx blocked stations (with CS bit). If we heard
+ * frames from a blocked station on a new channel we can
+ * TX to it again.
+ */
+ if (unlikely(mvm->csa_tx_block_bcn_timeout))
+ iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
+
rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
@@ -369,11 +381,10 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
if (trig_check && rx_status->signal < rssi)
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
}
- }
-
- if (sta && ieee80211_is_data(hdr->frame_control))
- iwl_mvm_rx_csum(sta, skb, rx_pkt_status);
+ if (ieee80211_is_data(hdr->frame_control))
+ iwl_mvm_rx_csum(sta, skb, rx_pkt_status);
+ }
rcu_read_unlock();
/* set the preamble flag if appropriate */