From patchwork Sun Jul 6 09:36:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emmanuel Grumbach X-Patchwork-Id: 4489821 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DFE4A9F1AC for ; Sun, 6 Jul 2014 09:37:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EC64920253 for ; Sun, 6 Jul 2014 09:37:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E5C3C2024C for ; Sun, 6 Jul 2014 09:37:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751735AbaGFJhp (ORCPT ); Sun, 6 Jul 2014 05:37:45 -0400 Received: from mail-wi0-f170.google.com ([209.85.212.170]:56571 "EHLO mail-wi0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751629AbaGFJhR (ORCPT ); Sun, 6 Jul 2014 05:37:17 -0400 Received: by mail-wi0-f170.google.com with SMTP id cc10so13686971wib.1 for ; Sun, 06 Jul 2014 02:37:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=eVdDwFHaeDu8jqNMYWuFlR9WNeO2sKgLdV0aA76k2dg=; b=Ubr48pZ/sWBEGFP/02CJkB4MozRMy3cVpQlq703nCKcaOrCs9aWOgAAgCu29voKGvB pHvxjqkrc8T8dP9jAR9rm7Eva4GrMeatPxXNyEXYYaQuTtaY2HXa09EtcJHfGzx7hrwE E0D+o7mkxRJmpBGWIBVaIBxBg8BYpaCPOKFCiGnRuHrXmr/IBAXY/9W4iTs4aC5w0pkE wxMsppVTxfVY98BqauoUb0PycoAAG7q+BGqm0Td8YUYFyKyq1B8Ipl92Nghkzh60sMbz akm4cM3sMUwaaLZ8yCU/HhD4nwP2zbJKDZ3aVbxvNDmELp9OMrhjnjD79npKtRMx04tl HrZw== X-Received: by 10.180.101.98 with SMTP id ff2mr29673846wib.40.1404639436329; Sun, 06 Jul 2014 02:37:16 -0700 (PDT) Received: from localhost.localdomain (109-186-76-70.bb.netvision.net.il. [109.186.76.70]) by mx.google.com with ESMTPSA id 20sm79585207wjt.42.2014.07.06.02.37.14 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 06 Jul 2014 02:37:15 -0700 (PDT) From: Emmanuel Grumbach To: linux-wireless@vger.kernel.org Cc: Arik Nemtsov , Arik Nemtsov , Emmanuel Grumbach Subject: [PATCH 35/40] iwlwifi: mvm: disallow new TDLS stations when appropriate Date: Sun, 6 Jul 2014 12:36:11 +0300 Message-Id: <1404639376-3792-35-git-send-email-egrumbach@gmail.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <53B917DC.5050902@gmail.com> References: <53B917DC.5050902@gmail.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Arik Nemtsov HW/FW constraints dictate that TDLS should only be used when a single phy ctx is active. We also support at most 4 TDLS peers. We don't support TDLS on a P2P vif. Unify and move a phy-ctx counting implementation from the power-mgmt code in order to simplify implementation. Signed-off-by: Arik Nemtsov Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/fw-api.h | 2 ++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 30 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 26 +++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/power.c | 22 +-------------------- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 99329ed..b8e4e78 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -86,6 +86,8 @@ enum { #define IWL_MVM_STATION_COUNT 16 +#define IWL_MVM_TDLS_STA_COUNT 4 + /* commands */ enum { MVM_ALIVE = 0x1, diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 5ed6fb3..57945fe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1843,6 +1843,26 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, mutex_unlock(&mvm->mutex); } +static int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm) +{ + struct ieee80211_sta *sta; + int count = 0; + int i; + + lockdep_assert_held(&mvm->mutex); + + for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { + sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], + lockdep_is_held(&mvm->mutex)); + if (!sta || IS_ERR(sta) || !sta->tdls) + continue; + + count++; + } + + return count; +} + static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1881,6 +1901,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ret = -EINVAL; goto out_unlock; } + + if (sta->tdls && + (vif->p2p || + iwl_mvm_tdls_sta_count(mvm) == IWL_MVM_TDLS_STA_COUNT || + iwl_mvm_phy_ctx_count(mvm) > 1)) { + IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n"); + ret = -EBUSY; + goto out_unlock; + } + ret = iwl_mvm_add_sta(mvm, vif, sta); } else if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_AUTH) { diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 7b308c4..c75b958 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -838,6 +838,7 @@ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt); void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt); +int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm); /* MAC (virtual interface) programming */ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 539f3a9..6cc243f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c @@ -261,3 +261,29 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) ctxt->ref--; } + +static void iwl_mvm_binding_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + unsigned long *data = _data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + if (!mvmvif->phy_ctxt) + return; + + if (vif->type == NL80211_IFTYPE_STATION || + vif->type == NL80211_IFTYPE_AP) + __set_bit(mvmvif->phy_ctxt->id, data); +} + +int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm) +{ + unsigned long phy_ctxt_counter = 0; + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_binding_iterator, + &phy_ctxt_counter); + + return hweight8(phy_ctxt_counter); +} diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index c182a8b..3b582dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -246,30 +246,10 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; } -static void iwl_mvm_binding_iterator(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - unsigned long *data = _data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - - if (!mvmvif->phy_ctxt) - return; - - if (vif->type == NL80211_IFTYPE_STATION || - vif->type == NL80211_IFTYPE_AP) - __set_bit(mvmvif->phy_ctxt->id, data); -} - static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - unsigned long phy_ctxt_counter = 0; - - ieee80211_iterate_active_interfaces_atomic(mvm->hw, - IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_binding_iterator, - &phy_ctxt_counter); if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, ETH_ALEN)) @@ -291,7 +271,7 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, * Avoid using uAPSD if client is in DCM - * low latency issue in Miracast */ - if (hweight8(phy_ctxt_counter) >= 2) + if (iwl_mvm_phy_ctx_count(mvm) >= 2) return false; return true;