Commit 09b4a4fa authored by Johannes Berg's avatar Johannes Berg

mac80211: introduce capability flags for VHT EXT NSS support

Depending on whether or not rate control supports selecting
rates depending on the bandwidth, we can use VHT extended
NSS support. In essence, this is dot11VHTExtendedNSSBWCapable
from the spec, since depending on that we'll need to parse
the bandwidth.

If needed, also set/clear the VHT Capability Element bit for
this capability so that we don't advertise it erroneously or
don't advertise it when we actually use it.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b0aa75f0
...@@ -2137,6 +2137,12 @@ struct ieee80211_txq { ...@@ -2137,6 +2137,12 @@ struct ieee80211_txq {
* @IEEE80211_HW_BUFF_MMPDU_TXQ: use the TXQ for bufferable MMPDUs, this of * @IEEE80211_HW_BUFF_MMPDU_TXQ: use the TXQ for bufferable MMPDUs, this of
* course requires the driver to use TXQs to start with. * course requires the driver to use TXQs to start with.
* *
* @IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW: (Hardware) rate control supports VHT
* extended NSS BW (dot11VHTExtendedNSSBWCapable). This flag will be set if
* the selected rate control algorithm sets %RATE_CTRL_CAPA_VHT_EXT_NSS_BW
* but if the rate control is built-in then it must be set by the driver.
* See also the documentation for that flag.
*
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/ */
enum ieee80211_hw_flags { enum ieee80211_hw_flags {
...@@ -2183,6 +2189,7 @@ enum ieee80211_hw_flags { ...@@ -2183,6 +2189,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP, IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP, IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
IEEE80211_HW_BUFF_MMPDU_TXQ, IEEE80211_HW_BUFF_MMPDU_TXQ,
IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW,
/* keep last, obviously */ /* keep last, obviously */
NUM_IEEE80211_HW_FLAGS NUM_IEEE80211_HW_FLAGS
...@@ -5655,7 +5662,22 @@ struct ieee80211_tx_rate_control { ...@@ -5655,7 +5662,22 @@ struct ieee80211_tx_rate_control {
bool bss; bool bss;
}; };
/**
* enum rate_control_capabilities - rate control capabilities
*/
enum rate_control_capabilities {
/**
* @RATE_CTRL_CAPA_VHT_EXT_NSS_BW:
* Support for extended NSS BW support (dot11VHTExtendedNSSCapable)
* Note that this is only looked at if the minimum number of chains
* that the AP uses is < the number of TX chains the hardware has,
* otherwise the NSS difference doesn't bother us.
*/
RATE_CTRL_CAPA_VHT_EXT_NSS_BW = BIT(0),
};
struct rate_control_ops { struct rate_control_ops {
unsigned long capa;
const char *name; const char *name;
void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
void (*free)(void *priv); void (*free)(void *priv);
......
...@@ -216,6 +216,7 @@ static const char *hw_flag_names[] = { ...@@ -216,6 +216,7 @@ static const char *hw_flag_names[] = {
FLAG(DEAUTH_NEED_MGD_TX_PREP), FLAG(DEAUTH_NEED_MGD_TX_PREP),
FLAG(DOESNT_SUPPORT_QOS_NDP), FLAG(DOESNT_SUPPORT_QOS_NDP),
FLAG(BUFF_MMPDU_TXQ), FLAG(BUFF_MMPDU_TXQ),
FLAG(SUPPORTS_VHT_EXT_NSS_BW),
#undef FLAG #undef FLAG
}; };
......
...@@ -1199,6 +1199,9 @@ struct ieee80211_local { ...@@ -1199,6 +1199,9 @@ struct ieee80211_local {
/* number of RX chains the hardware has */ /* number of RX chains the hardware has */
u8 rx_chains; u8 rx_chains;
/* bitmap of which sbands were copied */
u8 sband_allocated;
int tx_headroom; /* required headroom for hardware/radiotap */ int tx_headroom; /* required headroom for hardware/radiotap */
/* Tasklet and skb queue to process calls from IRQ mode. All frames /* Tasklet and skb queue to process calls from IRQ mode. All frames
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH * Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -1158,6 +1159,51 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -1158,6 +1159,51 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_rate; goto fail_rate;
} }
if (local->rate_ctrl) {
clear_bit(IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW, hw->flags);
if (local->rate_ctrl->ops->capa & RATE_CTRL_CAPA_VHT_EXT_NSS_BW)
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
}
/*
* If the VHT capabilities don't have IEEE80211_VHT_EXT_NSS_BW_CAPABLE,
* or have it when we don't, copy the sband structure and set/clear it.
* This is necessary because rate scaling algorithms could be switched
* and have different support values.
* Print a message so that in the common case the reallocation can be
* avoided.
*/
BUILD_BUG_ON(NUM_NL80211_BANDS > 8 * sizeof(local->sband_allocated));
for (band = 0; band < NUM_NL80211_BANDS; band++) {
struct ieee80211_supported_band *sband;
bool local_cap, ie_cap;
local_cap = ieee80211_hw_check(hw, SUPPORTS_VHT_EXT_NSS_BW);
sband = local->hw.wiphy->bands[band];
if (!sband || !sband->vht_cap.vht_supported)
continue;
ie_cap = !!(sband->vht_cap.vht_mcs.tx_highest &
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE));
if (local_cap == ie_cap)
continue;
sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL);
if (!sband)
goto fail_rate;
wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",
band);
sband->vht_cap.vht_mcs.tx_highest ^=
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
local->hw.wiphy->bands[band] = sband;
local->sband_allocated |= BIT(band);
}
/* add one default STA interface if supported */ /* add one default STA interface if supported */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) && if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
!ieee80211_hw_check(hw, NO_AUTO_VIF)) { !ieee80211_hw_check(hw, NO_AUTO_VIF)) {
...@@ -1276,6 +1322,7 @@ static int ieee80211_free_ack_frame(int id, void *p, void *data) ...@@ -1276,6 +1322,7 @@ static int ieee80211_free_ack_frame(int id, void *p, void *data)
void ieee80211_free_hw(struct ieee80211_hw *hw) void ieee80211_free_hw(struct ieee80211_hw *hw)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
enum nl80211_band band;
mutex_destroy(&local->iflist_mtx); mutex_destroy(&local->iflist_mtx);
mutex_destroy(&local->mtx); mutex_destroy(&local->mtx);
...@@ -1291,6 +1338,12 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) ...@@ -1291,6 +1338,12 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
ieee80211_free_led_names(local); ieee80211_free_led_names(local);
for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!(local->sband_allocated & BIT(band)))
continue;
kfree(local->hw.wiphy->bands[band]);
}
wiphy_free(local->hw.wiphy); wiphy_free(local->hw.wiphy);
} }
EXPORT_SYMBOL(ieee80211_free_hw); EXPORT_SYMBOL(ieee80211_free_hw);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment