* [PATCH 6/8] rtlwifi: rtl8192ce: Fix missing blank lines
From: Larry Finger @ 2019-02-21 19:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190221193115.30848-1-Larry.Finger@lwfinger.net>
The problems filed include the following:
WARNING: Missing a blank line after declarations
CHECK: Please don't use multiple blank lines
There are no code changes.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 7 ++++++-
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c | 1 +
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c | 1 -
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c | 8 ++++++++
4 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index 7c94cabc19a6..10d85c2c7867 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -144,6 +144,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_BASIC_RATE:{
u16 rate_cfg = ((u16 *) val)[0];
u8 rate_index = 0;
+
rate_cfg &= 0x15f;
rate_cfg |= 0x01;
rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
@@ -197,6 +198,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_ACK_PREAMBLE:{
u8 reg_tmp;
u8 short_preamble = (bool)*val;
+
reg_tmp = (mac->cur_40_prime_sc) << 5;
if (short_preamble)
reg_tmp |= 0x80;
@@ -293,6 +295,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
}
case HW_VAR_AC_PARAM:{
u8 e_aci = *(val);
+
rtl92c_dm_init_edca_turbo(hw);
if (rtlpci->acm_method != EACMWAY2_SW)
@@ -456,6 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
break;
case HW_VAR_AID:{
u16 u2btmp;
+
u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
u2btmp &= 0xC000;
rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
@@ -661,6 +665,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
if (rtlpriv->btcoexist.bt_coexistence) {
u32 value32;
+
value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO);
value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK);
rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32);
@@ -1245,6 +1250,7 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtl92c_dm_init_edca_turbo(hw);
switch (aci) {
case AC1_BK:
@@ -2279,7 +2285,6 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw)
rtlpriv->btcoexist.reg_bt_sco = 0;
}
-
void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
index 8d18210dd5c8..f6574f31fa3b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
@@ -443,6 +443,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
bool rtstatus;
u32 initializecount = 0;
+
do {
initializecount++;
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
index e258b0803699..58878db404ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c
@@ -3,7 +3,6 @@
#include "table.h"
-
u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = {
0x024, 0x0011800f,
0x028, 0x00ffdb83,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index b08fb1bf6709..18a0ab59631a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
@@ -36,6 +36,7 @@ static u8 _rtl92c_query_rxpwrpercentage(s8 antpower)
static u8 _rtl92c_evm_db_to_percentage(s8 value)
{
s8 ret_val;
+
ret_val = value;
if (ret_val >= 0)
@@ -109,6 +110,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
if (is_cck_rate) {
u8 report, cck_highpwr;
+
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
if (ppsc->rfpwr_state == ERFON)
@@ -120,6 +122,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
if (!cck_highpwr) {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = cck_buf->cck_agc_rpt & 0xc0;
report = report >> 6;
switch (report) {
@@ -138,6 +141,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
}
} else {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = p_drvinfo->cfosho[0] & 0x60;
report = report >> 5;
switch (report) {
@@ -182,6 +186,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
/* (3) Get Signal Quality (EVM) */
if (packet_match_bssid) {
u8 sq;
+
if (pstats->rx_pwdb_all > 40)
sq = 100;
else {
@@ -318,6 +323,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
struct ieee80211_hdr *hdr;
u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
RX_DRV_INFO_SIZE_UNIT;
@@ -497,6 +503,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
if (sta) {
u8 ampdu_density = sta->ht_cap.ampdu_density;
+
SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
}
@@ -733,6 +740,7 @@ bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
if (hw_queue == BEACON_QUEUE) {
rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
} else {
--
2.20.1
^ permalink raw reply related
* [PATCH 7/8] rtlwifi: rtl8192cu: Fix problems with blank lines
From: Larry Finger @ 2019-02-21 19:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190221193115.30848-1-Larry.Finger@lwfinger.net>
The following problems were found:
WARNING: Missing a blank line after declarations
CHECK: Please don't use multiple blank lines
CHECK: Please use a blank line after function/struct/union/enum declarations
There are no code changes.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 9 ++++++++-
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h | 4 ----
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c | 8 +++++++-
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h | 3 ---
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 7 +++++++
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h | 2 --
6 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
index 52ee713d50f5..56cc3bc30860 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
@@ -747,6 +747,7 @@ static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw,
u8 queue_sel)
{
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
if (IS_NORMAL_CHIP(rtlhal->version))
_rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num,
queue_sel);
@@ -813,6 +814,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
u8 wmm_enable = false; /* TODO */
u8 out_ep_nums = rtlusb->out_ep_nums;
u8 queue_sel = rtlusb->out_queue_sel;
+
err = _rtl92cu_init_power_on(hw);
if (err) {
@@ -1013,6 +1015,7 @@ d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine
e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine
***************************************/
u8 erfpath = 0, value8 = 0;
+
rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
rtl_set_rfreg(hw, (enum radio_path)erfpath, 0x0, MASKBYTE0, 0x0);
@@ -1204,6 +1207,7 @@ static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 tmp1byte = 0;
+
if (IS_NORMAL_CHIP(rtlhal->version)) {
tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
@@ -1353,6 +1357,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
if (check_bssid) {
u8 tmp;
+
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
tmp = BIT(4);
@@ -1365,6 +1370,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
_rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
} else {
u8 tmp;
+
if (IS_NORMAL_CHIP(rtlhal->version)) {
reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
tmp = BIT(4);
@@ -1631,6 +1637,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
case HW_VAR_ACK_PREAMBLE:{
u8 reg_tmp;
u8 short_preamble = (bool)*val;
+
reg_tmp = 0;
if (short_preamble)
reg_tmp |= 0x80;
@@ -1881,6 +1888,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
break;
case HW_VAR_KEEP_ALIVE:{
u8 array[2];
+
array[0] = 0xff;
array[1] = *((u8 *)val);
rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2,
@@ -1963,7 +1971,6 @@ static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
if (nmode && ((curtxbw_40mhz &&
curshortgi_40mhz) || (!curtxbw_40mhz &&
curshortgi_20mhz))) {
-
ratr_value |= 0x10000000;
tmp_ratr_value = (ratr_value >> 12);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
index 0ccc47e36652..5c48c3fd45e4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h
@@ -14,14 +14,12 @@
#define TX_TOTAL_PAGE_NUMBER 0xF8
#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1)
-
#define CHIP_B_PAGE_NUM_PUBQ 0xE7
/* For Test Chip Setting
* (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */
#define CHIP_A_PAGE_NUM_PUBQ 0x7E
-
/* For Chip A Setting */
#define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5
#define WMM_CHIP_A_TX_PAGE_BOUNDARY \
@@ -31,8 +29,6 @@
#define WMM_CHIP_A_PAGE_NUM_HPQ 0x29
#define WMM_CHIP_A_PAGE_NUM_LPQ 0x29
-
-
/* Note: For Chip B Setting ,modify later */
#define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5
#define WMM_CHIP_B_TX_PAGE_BOUNDARY \
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index cc2ba74bff81..b3ce8000d52d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
@@ -24,7 +24,6 @@
#define RX_EVM rx_evm_percentage
#define RX_SIGQ rx_mimo_sig_qual
-
void rtl92c_read_chip_version(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -143,6 +142,7 @@ bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
} while (++count);
return status;
}
+
/**
* rtl92c_init_LLT_table - Init LLT table
* @io: io callback
@@ -189,6 +189,7 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
}
return rst;
}
+
void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
u8 *p_macaddr, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all)
@@ -370,6 +371,7 @@ void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
}
@@ -647,6 +649,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
pstats->RX_SIGQ[1] = -1;
if (is_cck_rate) {
u8 report, cck_highpwr;
+
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
if (!in_powersavemode)
cck_highpwr = rtlphy->cck_high_power;
@@ -654,6 +657,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
cck_highpwr = false;
if (!cck_highpwr) {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = cck_buf->cck_agc_rpt & 0xc0;
report = report >> 6;
switch (report) {
@@ -672,6 +676,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
}
} else {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+
report = p_drvinfo->cfosho[0] & 0x60;
report = report >> 5;
switch (report) {
@@ -694,6 +699,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
pstats->recvsignalpower = rx_pwr_all;
if (packet_match_bssid) {
u8 sq;
+
if (pstats->rx_pwdb_all > 40)
sq = 100;
else {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
index 62eb3c5adec1..dd76a05829d5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
@@ -18,7 +18,6 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw);
void rtl92c_disable_interrupt(struct ieee80211_hw *hw);
void rtl92c_set_qos(struct ieee80211_hw *hw, int aci);
-
/*---------------------------------------------------------------
* Hardware init functions
*---------------------------------------------------------------*/
@@ -130,6 +129,4 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
* Card disable functions
*---------------------------------------------------------------*/
-
-
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 4293d0640310..0020adc004a5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -108,6 +108,7 @@ static void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg,
struct rtl_ep_map *ep_map)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
if (bwificfg) { /* for WMM */
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"USB 3EP Setting for WMM.....\n");
@@ -141,6 +142,7 @@ static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
ep_map->ep_mapping[RTL_TXQ_HI] = 2;
}
+
static int _out_ep_mapping(struct ieee80211_hw *hw)
{
int err = 0;
@@ -174,11 +176,13 @@ static int _out_ep_mapping(struct ieee80211_hw *hw)
return err;
}
+
/* endpoint mapping */
int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw)
{
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
int error = 0;
+
if (likely(IS_NORMAL_CHIP(rtlhal->version)))
error = configvernoutep(hw);
else
@@ -442,6 +446,7 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc)
SET_TX_DESC_LAST_SEG(txdesc, 1);
SET_TX_DESC_FIRST_SEG(txdesc, 1);
}
+
/**
* For HW recovery information
*/
@@ -531,11 +536,13 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
sta = ieee80211_find_sta(mac->vif, mac->bssid);
if (sta) {
u8 ampdu_density = sta->ht_cap.ampdu_density;
+
SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density);
}
rcu_read_unlock();
if (info->control.hw_key) {
struct ieee80211_key_conf *keyconf = info->control.hw_key;
+
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index 439ced0e18fa..ae2e8aa212de 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -198,7 +198,6 @@ struct rx_drv_info_92c {
#define SET_TX_DESC_OWN(__txdesc, __value) \
SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value)
-
/* Dword 1 */
#define SET_TX_DESC_MACID(__txdesc, __value) \
SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value)
@@ -355,7 +354,6 @@ struct rx_drv_info_92c {
#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \
SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value)
-
int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
--
2.20.1
^ permalink raw reply related
* [PATCH 8/8] rtlwifi: rtl8192com: Fix blank line problems
From: Larry Finger @ 2019-02-21 19:31 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190221193115.30848-1-Larry.Finger@lwfinger.net>
The following types of blank line problems are reported:
WARNING: Missing a blank line after declarations
CHECK: Please don't use multiple blank lines
There are no code changes.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 6 ++----
drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c | 5 ++---
drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c | 1 -
drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c | 1 +
4 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
index 2d5664ab011e..00d3b7015f82 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
@@ -425,7 +425,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
-
if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
dm_digtable->rssi_val_min =
rtl92c_dm_initial_gain_min_pwdb(hw);
@@ -504,7 +503,6 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
rtl92c_dm_cck_packet_detection_thresh(hw);
dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
-
}
static void rtl92c_dm_dig(struct ieee80211_hw *hw)
@@ -607,6 +605,7 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtlpriv->dm.current_turbo_edca = false;
rtlpriv->dm.is_any_nonbepkts = false;
rtlpriv->dm.is_cur_rdlstate = false;
@@ -660,7 +659,6 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
(!rtlpriv->dm.disable_framebursting))) {
-
cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
@@ -685,6 +683,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
} else {
if (rtlpriv->dm.current_turbo_edca) {
u8 tmp = AC0_BE;
+
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
&tmp);
rtlpriv->dm.current_turbo_edca = false;
@@ -1634,7 +1633,6 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
-
/* Only enable HW BT coexist when BT in "Busy" state. */
if (rtlpriv->mac80211.vendor == PEER_CISCO &&
rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
index 6af72799e09c..18c76990a089 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
@@ -18,6 +18,7 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+
if (enable)
value32 |= MCUFWDL_EN;
else
@@ -25,8 +26,8 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
u8 tmp;
- if (enable) {
+ if (enable) {
tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
tmp | 0x04);
@@ -37,7 +38,6 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
} else {
-
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
@@ -622,7 +622,6 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
"rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
u1rsvdpageloc, 3);
-
skb = dev_alloc_skb(totalpacketlen);
skb_put_data(skb, &reserved_page_packet, totalpacketlen);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
index e8af1952d243..97ad21c3964f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c
@@ -4,7 +4,6 @@
#include "../wifi.h"
#include <linux/module.h>
-
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Georgia <georgia@realtek.com>");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
index c6a3ed441c3f..0efd19aa4fe5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
@@ -747,6 +747,7 @@ static void _rtl92c_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) {
if (channel == 6 &&
rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
--
2.20.1
^ permalink raw reply related
* Re: [RFC PATCH v3 03/12] mac80211: IEEE 802.11 Extended Key ID support
From: Alexander Wetzel @ 2019-02-21 19:47 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <e27bffe8-4c75-34d9-b326-39ffb05b73eb@wetzel-home.de>
>>>
>>> - Enforce cipher does not change when replacing a key.
>>
>> is that actually required somehow?
>
> The code is silently assuming a rekey is using the same cipher. Someone
> e.g. switching from WEP to CCMP with a rekey would pass all sanity
> checks and allow to use the code in a way never intended or tested.
> With the current handling the userspace e.g. should be able to install a
> WEB key using keyid 3 and then rekey it with a CCMP key, claiming keyid
> 0 bit mac80211 will copy the keyid from the old and use keyid 3.
> Something not possible otherwise.
>
> That said I do not see how this could be exploited, I simply try to
> enforce all assumptions to be on the safe side. (I did not dig deeper
> into potential exploits after finding out how keyids are used during
> rekey.)
>
>
>>> + * @EXT_SET_KEY: a new key must be set but is only valid for decryption
>>> + * @EXT_KEY_RX_TX: a key installed with @EXT_SET_KEY is becoming the
>>> + * designated Rx/Tx key for the station
>>
>> Not sure I like the EXT_SET_KEY. There's also no "designated Rx key", is
>> there? It's always selected by key ID.
>>
>> How about SET_KEY_RXONLY and SET_KEY_TX or something like that?
>>
>
> First, you are of course right about the designated Rx key. I'll update
> that.
>
> Second, I spend quite some time finding good names for the calls and one
> of the last tweaks to this patch was replacing SET_KEY_RX_ONLY to
> EXT_SET_KEY...
>
> So here the reasoning for why I named them as they are and why I prefer
> the names used in the patch.
> First, many drivers will handle SET_KEY and SET_KEY_RX_ONLY with the
> same code and not differentiate between those at all. Using EXT_as a
> prefix for the "normal" command is therefore a nice way to imply the
> command can only be used with Extended Key ID and still link it to the
> original command.
> But more important for me was the clash between what the command spells
> and what it does in the COMPAT mode: SET_KEY_RX_ONLY would then be used
> to install a TX only key which never can be used by the card for Rx.
> So I decided to rename it to EXT_SET_KEY, just indicating that this
> command adds a new key to the card for Extended Key ID and drop the
> confusing reference to Rx.
>
> I also had a comparable problem with SET_KEY_TX:
> Most cards will already have done what must be done to use a key for Tx
> with the first command. Only ath10k (assuming it could support Extended
> Key ID at all) would really switch Tx with this command.
> All other drivers seem to lookup the hw key ID and use whatever key is
> referenced there. In fact I think most NATIVE drivers won't have to do
> anything here and just can return 0.
> Now COMPAT drivers (normally) will normally need a new special command
> to enable Rx crypto offload for the new key. So we either would have to
> add a new command for COMPAT drivers or accept that SET_KEY_TX is used
> for that, again putting quite some stain an the name.
>
> Using EXT_SET_KEY instead just implies that we are adding a new key for
> Extended Key IDs and it's our first contact with this key.
> EXT_KEY_RX_TX is then the second contact and has to do whatever is
> necessary to switch the added but not yet fully activated key to fully
> activated. That COPMPAT drivers will enable Rx with it while native
> drivers do nothing or really switch Tx with the command.
>
> Long story short: Using SET_KEY_RXONLY and SET_KEY_TX is not wrong, but
> I would rate them more confusing.
>
>>> +static int ieee80211_set_tx_key(struct ieee80211_sub_if_data *sdata,
>>> + const u8 *mac_addr, u8 key_idx)
>>> +{
>>> + struct ieee80211_local *local = sdata->local;
>>> + struct ieee80211_key *key;
>>> + struct sta_info *sta;
>>> + int ret;
>>> +
>>> + if (!wiphy_ext_feature_isset(local->hw.wiphy,
>>> + NL80211_EXT_FEATURE_EXT_KEY_ID))
>>> + return -EINVAL;
>>
>> You set this, wouldn't it make more sense to check EXT_KEY_ID_NATIVE?
>>
>> Or maybe this is because of the next patch?
>
> Exactly. Assuming we merge NATIVE and drop COMPAT that would move down
> to the driver.
My first answer for that on makes no sense, so let me try again:
Exactly. With COMPAT we would have to check for EXT_KEY_ID_NATIVE and
EXT_KEY_ID_COMPAT. Since we have already done that and set
NL80211_EXT_FEATURE_EXT_KEY_ID I check that here.
Assuming we merge NATIVE and drop COMPAT it may make sense to keep the
check here and drop EXT_KEY_ID_NATIVE altogether.
The drivers than can set NL80211_EXT_FEATURE_EXT_KEY_ID directly.
>
>>
>>> + sta = sta_info_get_bss(sdata, mac_addr);
>>> +
>>> + if (!sta)
>>> + return -EINVAL;
>>> +
>>> + if (sta->ptk_idx == key_idx)
>>> + return 0;
>>> +
>>> + mutex_lock(&local->key_mtx);
>>> + key = key_mtx_dereference(local, sta->ptk[key_idx]);
>>> +
>>> + if (key && key->flags & KEY_FLAG_RX_ONLY)
>>
>> do you even need the flag? Isn't it equivalent to checking
>> sta->ptk_idx != key->idx
>> or so?
>>
>> Less data to maintain would be better.
>
> I have to look at that again. It will change some assumptions for sure
> but still could work out with some slight differences. I'll have to look
> deeper into that since I remember two moments where I was sure needing
> the flag. That may well be outdated, but at a first glance it would at
> least open the door to first install two key in legacy mode and then
> switch between them. (Which should be no problem, of course)
> I'll follow up on that separately, but that may take some time. When it
> works you'll get a new RFC.
>
>>
>>> + bool ext_native = ieee80211_hw_check(&local->hw,
>>> EXT_KEY_ID_NATIVE);
>>
>> you sort of only need this in the next patch, but I guess it doesn't
>> matter that much
>>
> Ups, yes. Forgot that when I split it in two patches some weeks ago,
>
>>> +int ieee80211_key_activate_tx(struct ieee80211_key *key)
>>> +{
>>> + struct ieee80211_sub_if_data *sdata = key->sdata;
>>> + struct sta_info *sta = key->sta;
>>> + struct ieee80211_local *local = key->local;
>>> + struct ieee80211_key *old;
>>> + int ret;
>>> +
>>> + assert_key_lock(local);
>>> +
>>> + key->flags &= ~KEY_FLAG_RX_ONLY;
>>> +
>>> + if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
>>> + key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
>>> + IEEE80211_KEY_FLAG_PUT_MIC_SPACE |
>>> + IEEE80211_KEY_FLAG_RESERVE_TAILROOM))
>>> + increment_tailroom_need_count(sdata);
>>> +
>>> + if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
>>> + ret = drv_set_key(local, EXT_KEY_RX_TX, sdata,
>>> + &sta->sta, &key->conf);
>>> + if (ret) {
>>> + sdata_err(sdata,
>>> + "failed to activate key for Tx (%d, %pM)\n",
>>> + key->conf.keyidx, sta->sta.addr);
>>> + return ret;
>>
>> You've already cleared the RX_ONLY flag, which gets you inconsistent
>> data now.
>>
>
> I don't think so, it looks ok for me. But the delay_tailroom logic took
> a surprisingly large chunk of time and I should explain how the updated
> logic is intended to work. Maybe I've messed it up somehow and just do
> not see it:
>
> I decided to handle that exact, no shortcuts. Only keys which can be
> used for Tx will be counted for delay tailroom. So when installing a Rx
> only key tailroom_needed will never be increased.
> Prior to enabling Tx with a key the code above drops the RX_ONLY flag
> and then evaluates if we have to call increment_tailroom_need_count. The
> key is then activated for Tx a few lines below, the old key is set to
> RX_ONLY and - assuming the old key also increased the tailroom needed
> counter - decrements it for the old key.
> (And I'm not sure if I should get that working without a dedicated key
> flag, but let's wait and see how that would look like and then discuss it.)
>
> The obvious simplification would be to just skip both steps and neither
> increment nor decrement tailroom needed. Problem with that is, that the
> HW offload decides during key install if the driver can support HW
> offload or not. So it could be that e.g. the old key did use HW
> encryption but the new will not. Handling that would further complicated
> by the fact that a key install also could failand then would have to
> clean up that again.
> So I just update tailroom_needed as soon as possible, allowing to abort
> any time and not worry about all that.
>
>>> + }
>>> + }
>>> +
>>> + old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
>>> + sta->ptk_idx = key->conf.keyidx;
>>
>> but you set this only here.
>>
>>> - /* Stop TX till we are on the new key */
>>> + /* Stop Tx till we are on the new key */
>>
>> Uh, I had to read that three times ... please don't make changes like
>> that? :)
>
> Noted, will drop all of those changes.
>
>>
>>> old_key->flags |= KEY_FLAG_TAINTED;
>>> ieee80211_clear_fast_xmit(sta);
>>> - /* Aggregation sessions during rekey are complicated due to the
>>> + /* Aggregation sessions during rekey are complicated by the
>>
>> similarly here, please don't make drive-by comment wording issues (also,
>> I'm not sure I agree - the old version just treats "complicated" as an
>> adjective, you treat it as a verb, but ultimately doesn't really matter?
>>
>>> #define NUM_DEFAULT_KEYS 4
>>> #define NUM_DEFAULT_MGMT_KEYS 2
>>> +#define INVALID_PTK_KEYIDX 2 /* Existing key slot never used by PTK
>>> keys */
>>
>> We could also use something obviously wrong like 0xff?
>
> No, not without some undesired modifications. We actually fetch the
> referenced key and the key slot must exist and be NULL. We (mostly)
> discussed that in the previous RFC, I just decided to use a define
> instead the numeric value. (Mostly due the fact that A-MPDU also needs
> an "invalid" ID and using the same looks like a good idea.
>
> Here how we use this #define in sta_info.c
>
> /* Extended Key ID can install keys for keyid 0 and 1 as Rx only.
> * Tx starts uses a key as soon as a key is installed in the slot
> * ptk_idx references to. To avoid using the initial Rx key prematurely
> * for Tx we initialize ptk_idx to a value never used, making sure the
> * referenced key is always NULL till ptk_idx is set to a valid value.
> */
> BUILD_BUG_ON(ARRAY_SIZE(sta->ptk) <= INVALID_PTK_KEYIDX);
> sta->ptk_idx = INVALID_PTK_KEYIDX;
> sta->ptk_idx_next = INVALID_PTK_KEYIDX;
>
>>
>>> +++ b/net/mac80211/tx.c
>>> @@ -3000,23 +3000,15 @@ void ieee80211_check_fast_xmit(struct
>>> sta_info *sta)
>>> switch (build.key->conf.cipher) {
>>> case WLAN_CIPHER_SUITE_CCMP:
>>> case WLAN_CIPHER_SUITE_CCMP_256:
>>> - /* add fixed key ID */
>>> - if (gen_iv) {
>>> - (build.hdr + build.hdr_len)[3] =
>>> - 0x20 | (build.key->conf.keyidx << 6);
>>> + if (gen_iv)
>>> build.pn_offs = build.hdr_len;
>>> - }
>>> if (gen_iv || iv_spc)
>>> build.hdr_len += IEEE80211_CCMP_HDR_LEN;
>>> break;
>>> case WLAN_CIPHER_SUITE_GCMP:
>>> case WLAN_CIPHER_SUITE_GCMP_256:
>>> - /* add fixed key ID */
>>> - if (gen_iv) {
>>> - (build.hdr + build.hdr_len)[3] =
>>> - 0x20 | (build.key->conf.keyidx << 6);
>>> + if (gen_iv)
>>> build.pn_offs = build.hdr_len;
>>> - }
>>> if (gen_iv || iv_spc)
>>> build.hdr_len += IEEE80211_GCMP_HDR_LEN;
>>> break;
>>> @@ -3383,6 +3375,7 @@ static void ieee80211_xmit_fast_finish(struct
>>> ieee80211_sub_if_data *sdata,
>>> pn = atomic64_inc_return(&key->conf.tx_pn);
>>> crypto_hdr[0] = pn;
>>> crypto_hdr[1] = pn >> 8;
>>> + crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6);
>>> crypto_hdr[4] = pn >> 16;
>>> crypto_hdr[5] = pn >> 24;
>>> crypto_hdr[6] = pn >> 32;
>>
>> This shouldn't be needed, you do update the fast TX cache when changing
>> the key?
>
> That's only right for the push path but can send out wrong packets when
> the driver is using the pull path:
>
> 1) ieee80211_xmit_fast() will use fast_tx structure to fill in the
> "cached" keyid and queue the packet. (let's say 0)
>
> 2) ieee80211_check_fast_xmit is called due to a rekey (and keyid change
> from 0 -> 1)
>
> 3) ieee80211_tx_dequeue() will then dequeue the prepared skb from 1),
> refresh the key information but keep keyid 0 in the skb and instruct the
> driver to encrypt it for keyid 1 -> WRONG
>
> 4) The remote sta tries to decrypt the packet using the key 0, as
> referenced by the keyid. Which will of course not work.
>
> With Extended Key ID (and some debugging) I added a simple rule: When
> you assign the pn you also set the matching keyid.
>
> Alexander
^ permalink raw reply
* Re: [RFC PATCH v3 04/12] mac80211: Compatibility Extended Key ID support
From: Alexander Wetzel @ 2019-02-21 20:07 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <0519f25cf73d8a91202e40b08e94de8d2520411e.camel@sipsolutions.net>
>
>> + if (!ext_native && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
>> + key->flags |= KEY_FLAG_RX_SW_CRYPTO;
>> + /* Activate Rx crypto offload after max 10s when idle */
>> + ieee80211_queue_delayed_work(&local->hw, &sta->ext_key_compat_wk,
>> + round_jiffies_relative(HZ * 10));
>> + }
>
> Is there much point in this?
>
>> + if (unlikely(rx->key->flags & KEY_FLAG_RX_SW_CRYPTO)) {
>> + rx->key->flags &= ~KEY_FLAG_RX_SW_CRYPTO;
>> + cancel_delayed_work(&rx->sta->ext_key_compat_wk);
>> + ieee80211_queue_delayed_work(&rx->local->hw,
>> + &rx->sta->ext_key_compat_wk, 0);
>> + }
>
> We'll almost certainly do it from here, so never exercise the other
> path?
This is mostly to have a definite time we know the new key is used also
for RX. In probably 99.9% of all cases it will be triggered from the Rx
path.
Some special purpose devices may not send any packets for a long time
and trigger the fallback, as (wrong) firewall rules. (I've e.g. tested
it by dropping all outgoing packets on the remote sta.)
The idea was to be sure that a rekey intervall >10s prevents activating
Rx crypt when rekeying the next key. Which now sounds kind of thin...
So I'll remove the 10s fallback.
^ permalink raw reply
* Re: [RFC PATCH v3 05/12] mac80211: Mark A-MPDU keyid borders for drivers
From: Alexander Wetzel @ 2019-02-21 21:20 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <c64a7a722fefe698e86dbc61ab4d6d2e087ae853.camel@sipsolutions.net>
Am 15.02.19 um 12:50 schrieb Johannes Berg:
>
>> The intent of the wording was probably written without considering
>> Extended Key IDs. At least it makes no sense for me to forbid mixing
>> MPDUs using keyid 0 and 1 in one A-MPDU.
>
> I think it may make sense - reprogramming the hardware engines may take
> some time, and doing that in the middle of the A-MPDU may not be
> feasible? You don't just have to load the key (that you need to do
> anyway) but also extract the status? I dunno, I'm more handwaving, but
> it doesn't make sense to add such a requirement when only one key index
> can be used to start with.
>
I'm pretty new to all that and I know I have still huge gaps everywhere.
But the card must be able to process MPDUs using both KeyIDs at that
moment already. When receiving a A-MPDU it should not be very hard to
check each MPDU and process it accordingly. (TX should even be simpler:
The driver simply can decide if he want's to have a key border in the
A-MPDU or not and switch to key when it wants.)
Forbidding to mix unicast with both keyIDs is adding an ugly overhead to
an otherwise quite simple solution and adds complexity, at least for us
here.
So while I would like to understand the reason for that rule it's still
a rule and breaking it seems to be a bad idea.
>> The code is assuming that the driver is not aggregating MPDUs more than
>> 5s apart. We probably don't have wait nearly so long but I'm not sure
>> what is the minimum time.
>
> OTOH, if you have a lot of BE/VI/VO traffic BK might be starved even
> longer than that, technically indefinitely.
>
Hm, there is nothing preventing us to drop this "idle" switch as long as
we also drop the 10s Rx accel offload when idle fallback in the COMPAT
patch. (We have to drop the RX idle accel patch or get a small risk of
dropping packets in unlikely but possible scenarios. If that are eapol
packets things will become hairy, probably disconnecting the sta.)
It just feels strange to potentially still use the old key for one
packet more without time limit. It could be, that the first EAPOL packet
we send for the next rekey would still use the previous key, the second
eapol packet the current.
>> +static struct ieee80211_key debug_noinline
>> +*ieee80211_select_sta_key(struct ieee80211_tx_data *tx)
>> +{
>> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
>> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
>> + struct sta_info *sta = tx->sta;
>> + struct ieee80211_key *key;
>> + struct ieee80211_key *next_key;
>> +
>> + key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]);
>> +
>> + if (likely(sta->ptk_idx_next == INVALID_PTK_KEYIDX))
>> + return key;
>> +
>> + /* Only when using Extended Key ID the code below can be executed */
>> +
>> + if (!ieee80211_is_data_present(hdr->frame_control))
>> + return key;
>> +
>> + if (sta->ptk_idx_next == sta->ptk_idx) {
>> + /* First packet using new key with A-MPDU active*/
>> + sta->ptk_idx_next = INVALID_PTK_KEYIDX;
>> + ieee80211_check_fast_xmit(tx->sta);
>
> I'm not convinced you can call this from this context? It looks safe
> though, but it's really strange in a way.
>
Well, it's seems to work fine, no warnings or problems so far:-)
But I also had doubts and only after finding out that
ieee80211_check_fast_xmit() is already being called from the same
context I dared to use it, see ieee80211_tx_prepare().
>> + info->flags &= ~IEEE80211_TX_CTL_AMPDU;
>
> Like you say above, I don't think this really makes a lot of sense. If
> we don't have any free bits I guess we should try to find some ...
Well, all I can think of is quite invasive, so I hoped you would have a
better idea:
Move the flags out from CB and use the freed space for a pointer to the
new construct.
That will touch a ton of code and slow down things a bit.
The question here also would be, if we should use a struct able to
handle other extensions or just a long long for flags.
If it comes to that I would propose to merge the other patches up to
this one and then start looking into that...
Alexander
^ permalink raw reply
* Re: [PATCH v2 2/2] ath10k: Set sk_pacing_shift to 6 for 11AC WiFi chips
From: Toke Høiland-Jørgensen @ 2019-02-21 22:50 UTC (permalink / raw)
To: Ben Greear, Kalle Valo
Cc: Grant Grundler, Kan Yan, linux-wireless, Johannes Berg, wgong,
ath10k, wgong
In-Reply-To: <80d93903-0aac-ebde-711f-4d4254275aad@candelatech.com>
Ben Greear <greearb@candelatech.com> writes:
> On 2/21/19 9:15 AM, Toke Høiland-Jørgensen wrote:
>> Ben Greear <greearb@candelatech.com> writes:
>>
>>> On 2/21/19 8:37 AM, Toke Høiland-Jørgensen wrote:
>>>> Ben Greear <greearb@candelatech.com> writes:
>>>>
>>>>> On 2/21/19 8:10 AM, Kalle Valo wrote:
>>>>>> Toke Høiland-Jørgensen <toke@toke.dk> writes:
>>>>>>
>>>>>>> Grant Grundler <grundler@google.com> writes:
>>>>>>>
>>>>>>>> On Thu, Sep 6, 2018 at 3:18 AM Toke Høiland-Jørgensen <toke@toke.dk> wrote:
>>>>>>>>>
>>>>>>>>> Grant Grundler <grundler@google.com> writes:
>>>>>>>>>
>>>>>>>>>>> And, well, Grant's data is from a single test in a noisy
>>>>>>>>>>> environment where the time series graph shows that throughput is all over
>>>>>>>>>>> the place for the duration of the test; so it's hard to draw solid
>>>>>>>>>>> conclusions from (for instance, for the 5-stream test, the average
>>>>>>>>>>> throughput for 6 is 331 and 379 Mbps for the two repetitions, and for 7
>>>>>>>>>>> it's 326 and 371 Mbps) . Unfortunately I don't have the same hardware
>>>>>>>>>>> used in this test, so I can't go verify it myself; so the only thing I
>>>>>>>>>>> can do is grumble about it here... :)
>>>>>>>>>>
>>>>>>>>>> It's a fair complaint and I agree with it. My counter argument is the
>>>>>>>>>> opposite is true too: most ideal benchmarks don't measure what most
>>>>>>>>>> users see. While the data wgong provided are way more noisy than I
>>>>>>>>>> like, my overall "confidence" in the "conclusion" I offered is still
>>>>>>>>>> positive.
>>>>>>>>>
>>>>>>>>> Right. I guess I would just prefer a slightly more comprehensive
>>>>>>>>> evaluation to base a 4x increase in buffer size on...
>>>>>>>>
>>>>>>>> Kalle, is this why you didn't accept this patch? Other reasons?
>>>>>>>>
>>>>>>>> Toke, what else would you like to see evaluated?
>>>>>>>>
>>>>>>>> I generally want to see three things measured when "benchmarking"
>>>>>>>> technologies: throughput, latency, cpu utilization
>>>>>>>> We've covered those three I think "reasonably".
>>>>>>>
>>>>>>> Hmm, going back and looking at this (I'd completely forgotten about this
>>>>>>> patch), I think I had two main concerns:
>>>>>>>
>>>>>>> 1. What happens in a degraded signal situation, where the throughput is
>>>>>>> limited by the signal conditions, or by contention with other devices.
>>>>>>> Both of these happen regularly, and I worry that latency will be
>>>>>>> badly affected under those conditions.
>>>>>>>
>>>>>>> 2. What happens with old hardware that has worse buffer management in
>>>>>>> the driver->firmware path (especially drivers without push/pull mode
>>>>>>> support)? For these, the lower-level queueing structure is less
>>>>>>> effective at controlling queueing latency.
>>>>>>
>>>>>> Do note that this patch changes behaviour _only_ for QCA6174 and QCA9377
>>>>>> PCI devices, which IIRC do not even support push/pull mode. All the
>>>>>> rest, including QCA988X and QCA9984 are unaffected.
>>>>>
>>>>> Just as a note, at least kernels such as 4.14.whatever perform poorly when
>>>>> running ath10k on 9984 when acting as TCP endpoints. This makes them not
>>>>> really usable for stuff like serving video to lots of clients.
>>>>>
>>>>> Tweaking TCP (I do it a bit differently, but either way) can significantly
>>>>> improve performance.
>>>>
>>>> Differently how? Did you have to do more than fiddle with the pacing_shift?
>>>
>>> This one, or a slightly tweaked version that applies to different kernels:
>>>
>>> https://github.com/greearb/linux-ct-4.16/commit/3e14e8491a5b31ce994fb2752347145e6ab7eaf5
>>
>> Right; but the current mac80211 default (pacing shift 8) corresponds to
>> setting your sysctl to 4...
>>
>>>>> Recently I helped a user that could get barely 70 stations streaming
>>>>> at 1Mbps on stock kernel (using one wave1 on 2.4, one wave-2 on 5Ghz),
>>>>> and we got 110 working with a tweaked TCP stack. These were /n
>>>>> stations too.
>>>>>
>>>>> I think it is lame that it _still_ requires out of tree patches to
>>>>> make TCP work well on ath10k...even if you want to default to current
>>>>> behaviour, you should allow users to tweak it to work with their use
>>>>> case.
>>>>
>>>> Well if TCP is broken to the point of being unusable I do think we
>>>> should fix it; but I think "just provide a configuration knob" should be
>>>> the last resort...
>>>
>>> So, it has been broken for years, and waiting for a perfect solution
>>> has not gotten the problem fixed.
>>
>> Well, the current default should at least be closer to something that
>> works well.
>>
>> I do think I may have erred on the wrong side of the optimum when I
>> submitted the original patch to set the default to 8; that should
>> probably have been 7 (i.e., 8 ms; the optimum in the evaluation we did
>> was around 6 ms, which is sadly not a power of two). Maybe changing that
>> default is actually better than having to redo the testing for all the
>> different devices as we're discussing in the context of this patch.
>> Maybe I should just send a patch to do that...
>
> It is hubris to think one setting works well for everyone. Sure, set a
> good default, but also let people tune the value.
Well I certainly won't object to a knob; I just don't think that most
people are going to use it, so we better make the default reasonable.
> And send the patches to stable so that users on older kernels can have
> good performance.
Sure, I can submit stable backports if needed :)
-Toke
^ permalink raw reply
* Re: [RFC PATCH v3 00/12] Draft for Extended Key ID support
From: Alexander Wetzel @ 2019-02-21 20:44 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <67c355e3b3078b55267c075d48b48bcb42435b11.camel@sipsolutions.net>
Am 15.02.19 um 12:10 schrieb Johannes Berg:
> On Sun, 2019-02-10 at 22:06 +0100, Alexander Wetzel wrote:
>>
>> The driver patches are - with the exception of the hwsim patch -
>> definitely not ready for merge and mostly here to illustrate how the
>> different APIs can be used and to start some discussions how to handle HW
>> specific challenges. Of course if someone wants to play with Extended Key
>> ID they also should be useful... (I can provide updated mostly working
>> hostapd/wpa_supplicant patches if someone is interested.
>
> Of course :-)
I've just upload my current hostapd patches here:
https://www.awhome.eu/index.php/s/FZx68eGMGbwf6EK
These are slightly updated versions of the patches I send to the hostapd
mailing list used in my tests. I'm using them since months in mixed
environments with and without Extennded Key ID support.
Once the nl80211 API stabilizes I'll plan to polish them, fill in the
known gaps and try to get them merged.
>
> Some tests for the hwsim tests there would also be nice, that's the
> easiest way to see something working - if you have them.
I did run the the existing PTK tests but proper tests for Extended Key
ID are the biggest open topic. I suspect proper tests will the most
complicated open task here.
The others are:
- No support for Extended Key ID in mesh mode
- Update to new kernel API (the one we extended for Extended KEY ID)
needs some more work.
- Make sure we do not install the keys twice when repeating either EAPOL
3 or 4 (I think one of them was ok, but I did not look at that for
ages... It's still working fine, mac80211 detects a duplicate key
install and just reports success.)
Alexander
^ permalink raw reply
* [PATCH 1/2] nl80211: Allow change CW to Ad-Hock network
From: Andrea Greco @ 2019-02-21 23:11 UTC (permalink / raw)
To: johannes.berg
Cc: Andrea Greco, Johannes Berg, David S. Miller, linux-wireless,
netdev, linux-kernel
From: Andrea Greco <a.greco@4sigma.it>
Add net-link support for change CW in Ad-Hock network
Signed-off-by: Andrea Greco <a.greco@4sigma.it>
---
net/wireless/nl80211.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d91a408db113..4fcc63fa4380 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2731,7 +2731,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO &&
+ netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
return -EINVAL;
if (!netif_running(netdev))
--
2.17.2
^ permalink raw reply related
* [PATCH 2/2] ath9K: debugfs: Fix SPUR-DOWN field
From: Andrea Greco @ 2019-02-21 23:12 UTC (permalink / raw)
To: johannes.berg
Cc: Andrea Greco, QCA ath9k Development, Kalle Valo, David S. Miller,
linux-wireless, netdev, linux-kernel
From: Andrea Greco <a.greco@4sigma.it>
SPUR DOWN field return spurup inside of spurdown
Signed-off-by: Andrea Greco <a.greco@4sigma.it>
---
drivers/net/wireless/ath/ath9k/debug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 4399e9ad058f..d4a2cdf9212c 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -148,7 +148,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
{ "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel },
{ "CCK LEVEL", ah->ani.cckNoiseImmunityLevel },
{ "SPUR UP", ah->stats.ast_ani_spurup },
- { "SPUR DOWN", ah->stats.ast_ani_spurup },
+ { "SPUR DOWN", ah->stats.ast_ani_spurdown },
{ "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon },
{ "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff },
{ "MRC-CCK ON", ah->stats.ast_ani_ccklow },
--
2.17.2
^ permalink raw reply related
* [PATCH] iw: allow to set wmm parameters from iw
From: Andrea Greco @ 2019-02-21 23:18 UTC (permalink / raw)
To: johannes; +Cc: johannes.berg, linux-wireless, Andrea Greco
From: Andrea Greco <a.greco@4sigma.it>
---
phy.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/phy.c b/phy.c
index 77df7a7..3154754 100644
--- a/phy.c
+++ b/phy.c
@@ -843,3 +843,83 @@ static int handle_get_txq(struct nl80211_state *state,
COMMAND(get, txq, "",
NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_get_txq,
"Get TXQ parameters.");
+
+static int handle_wmm_params(struct nl80211_state *state,
+ struct nl_msg *msg,
+ int argc, char **argv,
+ enum id_input id)
+{
+ char *end;
+ struct nlattr *txq, *params;
+ int queue, cw_min, cw_max, aifs, txop;
+
+ if (argc != 5)
+ return 1;
+
+ if (!strcmp(argv[0], "VO"))
+ queue = NL80211_TXQ_Q_VO;
+ else if (!strcmp(argv[0], "VI"))
+ queue = NL80211_TXQ_Q_VI;
+ else if (!strcmp(argv[0], "BK"))
+ queue = NL80211_TXQ_Q_BK;
+ else if (!strcmp(argv[0], "BE"))
+ queue = NL80211_TXQ_Q_BE;
+ else {
+ printf("Invalid parameter: %s\n", argv[0]);
+ return 2;
+ }
+
+ if (!*argv[1] || !*argv[2] || !*argv[3] || !*argv[4])
+ return 1;
+
+ cw_min = strtoul(argv[1], &end, 0);
+ if (*end)
+ return 1;
+
+ cw_max = strtoul(argv[2], &end, 0);
+ if (*end)
+ return 1;
+
+ aifs = strtoul(argv[3], &end, 0);
+ if (*end)
+ return 1;
+
+ txop = strtoul(argv[4], &end, 0);
+ if (*end)
+ return 1;
+
+ txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
+ if (!txq) {
+ goto nla_put_failure;
+ }
+
+ params = nla_nest_start(msg, 1);
+ if (!params) {
+ goto nla_put_failure;
+ }
+
+ NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, queue);
+ NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);
+ NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);
+ NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, txop);
+ NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);
+
+ nla_nest_end(msg,params);
+ nla_nest_end(msg,txq);
+
+ printf("cw_min:%d, cw_max:%d txop:%d aifs:%d\n", cw_min, cw_max, txop, aifs);
+
+ return 0;
+
+ nla_put_failure:
+ return -ENOBUFS;
+}
+
+COMMAND(set, wmm_params, "<VO|VI|BE|BK> <cw_min> <cw_max> <aifs> <txop>",
+ NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_wmm_params,
+ "Set WMM parameters for a queue (VO, VI, BE, or BK):\n"
+ " * cw_min/cw_max - contention window minimum/maximum\n"
+ " (a value of the form 2^n-1 in the range 1..32767)\n"
+ " * aifs - arbitration interframe spacing (0..255)\n"
+ " * txop - maximum burst time in units of 32 usecs, 0 meaning disabled\n"
+ );
--
2.17.2
^ permalink raw reply related
* Re: [PATCH v2] iwlwifi: mvm: Use div_s64 instead of do_div in iwl_mvm_debug_range_resp
From: Nick Desaulniers @ 2019-02-22 0:13 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Johannes Berg, Emmanuel Grumbach, Luca Coelho,
Intel Linux Wireless, Kalle Valo, linux-wireless, netdev, LKML,
Arnd Bergmann
In-Reply-To: <20190221080617.2795-1-natechancellor@gmail.com>
On Thu, Feb 21, 2019 at 12:08 AM Nathan Chancellor
<natechancellor@gmail.com> wrote:
>
> Clang warns:
>
> drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c:465:2: warning:
> comparison of distinct pointer types ('typeof ((rtt_avg)) *' (aka 'long
> long *') and 'uint64_t *' (aka 'unsigned long long *'))
> [-Wcompare-distinct-pointer-types]
> do_div(rtt_avg, 6666);
> ^~~~~~~~~~~~~~~~~~~~~
> include/asm-generic/div64.h:222:28: note: expanded from macro 'do_div'
> (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
> ~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~
> 1 warning generated.
>
> do_div expects an unsigned dividend. Use div_s64, which expects a signed
> dividend.
>
> Fixes: 937b10c0de68 ("iwlwifi: mvm: add debug prints for FTM")
> Link: https://github.com/ClangBuiltLinux/linux/issues/372
> Suggested-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> ---
>
> v1 -> v2:
>
> * Fix logic (as the return value of div{,64}_s64 must be used), thanks
> to Arnd for the review.
oh boy, sorry I missed that in the initial code review, thanks Arnd
for the sharp eye!
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Side tangent: we see this kind of difference in APIs a lot (modifying
the parameter vs returning a new value or making a copy then modifying
that) in C++ when a call site isn't passing the explicit address of
some variable or an identifier that's clearly a pointer. Ex.
int foo;
bar(foo);
Doesn't tell you whether bar mutates foo or not without looking at the
definition of bar, as it could be:
void bar(int x);
or
void bar(int& x);
I miss the convention in Ruby of using `!` suffixes on methods to
differentiate between such cases. ex:
"hello".capitalize
vs
"hello".capitalize!
both return the same value, but the one with the ! mutates the
existing object, while the one without creates a new object. And
that's a very standard convention throughout the standard library.
Whether or not people follow that convention is always another story.
One thing I'm curious about, is "why does do_div exist?" When should I
use do_div vs div_u64 (not div_s64 as is used in this patch)?
>
> drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
> index e9822a3ec373..94132cfd1f56 100644
> --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
> +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
> @@ -460,9 +460,7 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
> static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index,
> struct cfg80211_pmsr_result *res)
> {
> - s64 rtt_avg = res->ftm.rtt_avg * 100;
> -
> - do_div(rtt_avg, 6666);
> + s64 rtt_avg = div_s64(res->ftm.rtt_avg * 100, 6666);
>
> IWL_DEBUG_INFO(mvm, "entry %d\n", index);
> IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status);
> --
> 2.21.0.rc1
>
--
Thanks,
~Nick Desaulniers
^ permalink raw reply
* [PATCHv2 0/9] cfg80211/mac80211: Add support for TID specific configuration
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
Add infrastructure to support per TID configurations like noack policy,
retry count, AMPDU control(disable/enable), RTSCTS control(enable/disable)
and TX rate mask configurations.
This will be useful for the driver which can supports data TID
specific configuration rather than phy level configurations.
Here NL80211_CMD_SET_TID_CONFIG added to support this operation by
accepting TID configuration.
This command can accept STA mac addreess to make the configuration
station specific rather than applying to all the connected stations
to the netdev.
And this nested command configuration can accept multiple number of
data TID specific configuration in a single command,
enum ieee80211_tid_conf_mask used to notify the driver that which
configuration got modified for the TID.
Tamizh chelvam (9):
nl80211: New netlink command for TID specific configuration
nl80211: Add new netlink attribute for TID speicific retry count
nl80211: Add netlink attribute for AMPDU aggregation enable/disable
nl80211: Add netlink attribute to enable/disable RTS_CTS
nl80211: Add netlink attribute to configure TID specific tx rate
mac80211: Add api to support configuring TID specific configuration
ath10k: Add wmi command support for station specific TID config
ath10k: Add new api to support TID specific configuration
ath10k: Add extended TID configuration support
v2:
* Added support to accept multiple TID configuration
* Added support to configure TX rate and RTSCTS control
drivers/net/wireless/ath/ath10k/core.c | 4 +
drivers/net/wireless/ath/ath10k/core.h | 7 +
drivers/net/wireless/ath/ath10k/mac.c | 650 ++++++++++++++++++++++++++----
drivers/net/wireless/ath/ath10k/wmi-ops.h | 19 +
drivers/net/wireless/ath/ath10k/wmi.c | 33 ++
drivers/net/wireless/ath/ath10k/wmi.h | 72 ++++
include/net/cfg80211.h | 57 +++
include/net/mac80211.h | 35 ++
include/uapi/linux/nl80211.h | 181 +++++++++
net/mac80211/cfg.c | 28 ++
net/mac80211/driver-ops.h | 15 +
net/wireless/nl80211.c | 205 ++++++++++
net/wireless/rdev-ops.h | 11 +
net/wireless/trace.h | 18 +
14 files changed, 1255 insertions(+), 80 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCHv2 1/9] nl80211: New netlink command for TID specific configuration
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
Add a new NL command, NL80211_CMD_SET_TID_CONFIG to support
data TID specific configuration. This per TID configurations
are passed in NL80211_ATTR_TID_CONFIG which is a nested
attribute. This patch adds support to configure per TID
noack policy through NL80211_ATTR_TID_CONFIG_NOACK attribute.
Data TID value for this configuration will be passed through
NL80211_ATTR_TID_CONFIG_TID attribute. When the user-space wants
this configuration peer specific rather than being applied for
all the connected stations, MAC address of the peer can be passed
in NL80211_ATTR_MAC attribute. This patch introduced
enum ieee80211_tid_conf_mask to notify the driver that which
configuration modified.
Driver supporting data TID specific noack policy configuration
should be advertise through NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG
and supporting per STA data TID noack policy configuration
should be advertise through NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 35 +++++++++++++++
include/uapi/linux/nl80211.h | 51 ++++++++++++++++++++++
net/wireless/nl80211.c | 102 +++++++++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 11 +++++
net/wireless/trace.h | 18 ++++++++
5 files changed, 217 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f81677f..07eb2de 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -509,6 +509,35 @@ struct cfg80211_chan_def {
u32 center_freq2;
};
+enum ieee80211_tid_conf_mask {
+ IEEE80211_TID_CONF_NOACK = BIT(0),
+};
+
+/**
+ * struct ieee80211_tid_cfg - TID specific configuration
+ * @tid: TID number
+ * @tid_conf_mask: bitmap indicating which parameter changed
+ * see %enum ieee80211_tid_conf_mask
+ * @noack: noack configuration value for the TID
+ */
+struct ieee80211_tid_cfg {
+ u8 tid;
+ enum ieee80211_tid_conf_mask tid_conf_mask;
+ u8 noack;
+};
+
+/**
+ * struct ieee80211_tid_config - TID configuration
+ * @peer: Station's MAC address
+ * @n_tid_conf: Number of TID specific configurations to be applied
+ * @tid_conf: Configuration change info
+ */
+struct ieee80211_tid_config {
+ const u8 *peer;
+ u32 n_tid_conf;
+ struct ieee80211_tid_cfg tid_conf[];
+};
+
/**
* cfg80211_get_chandef_type - return old channel type from chandef
* @chandef: the channel definition
@@ -3436,6 +3465,10 @@ struct cfg80211_pmsr_request {
* Statistics should be cumulative, currently no way to reset is provided.
* @start_pmsr: start peer measurement (e.g. FTM)
* @abort_pmsr: abort peer measurement
+ * @set_tid_config: TID specific configuration. Apply this configuration for
+ * all the connected stations in the BSS if peer is NULL. Otherwise
+ * apply this configuration to the specific station.
+ * This callback may sleep.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3750,6 +3783,8 @@ struct cfg80211_ops {
struct cfg80211_pmsr_request *request);
void (*abort_pmsr)(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_pmsr_request *request);
+ int (*set_tid_config)(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_tid_config *tid_conf);
};
/*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index dd4f86e..c901a48 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1065,6 +1065,10 @@
* indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes
* determining the width and type.
*
+ * @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration
+ * is passed through this command using %NL80211_ATTR_TID_CONFIG
+ * nested attributes.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1285,6 +1289,8 @@ enum nl80211_commands {
NL80211_CMD_NOTIFY_RADAR,
+ NL80211_CMD_SET_TID_CONFIG,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -2308,6 +2314,9 @@ enum nl80211_commands {
* @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime
* scheduler.
*
+ * @NL80211_ATTR_TID_CONFIG: TID specific configuration in a
+ * nested attribute with %NL80211_ATTR_TID_* sub-attributes.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2759,6 +2768,8 @@ enum nl80211_attrs {
NL80211_ATTR_AIRTIME_WEIGHT,
+ NL80211_ATTR_TID_CONFIG,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -4543,6 +4554,39 @@ enum nl80211_tx_power_setting {
NL80211_TX_POWER_FIXED,
};
+enum nl80211_tid_config {
+ NL80211_TID_CONFIG_DEFAULT,
+ NL80211_TID_CONFIG_ENABLE,
+ NL80211_TID_CONFIG_DISABLE,
+};
+
+/* enum nl80211_attr_tid_config - TID specific configuration.
+ * @NL80211_ATTR_TID_CONFIG_TID: a TID value (u8 attribute).
+ * @NL80211_ATTR_TID_CONFIG_NOACK: Configure ack policy for the TID.
+ * specified in %NL80211_ATTR_TID_CONFIG_TID. see %enum nl80211_tid_config.
+ * Its type is u8, if the peer MAC address is passed in %NL80211_ATTR_MAC,
+ * then the noack configuration is applied to the data frame for the tid
+ * to that connected station. This configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, then this
+ * configuration should be treated as per-netdev configuration.
+ * This configuration will be cleared when the interface goes down and on
+ * the disconnection from a BSS. Driver supporting this feature should
+ * advertise NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG and
+ * NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG for supporting per sta
+ * configuration.
+ */
+enum nl80211_attr_tid_config {
+ __NL80211_ATTR_TID_INVALID,
+ NL80211_ATTR_TID_CONFIG_TID,
+ NL80211_ATTR_TID_CONFIG_NOACK,
+
+ /* keep last */
+ __NL80211_ATTR_TID_CONFIG_AFTER_LAST,
+ NL80211_ATTR_TID_CONFIG_MAX = __NL80211_ATTR_TID_CONFIG_AFTER_LAST - 1
+};
+
/**
* enum nl80211_packet_pattern_attr - packet pattern attribute
* @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
@@ -5343,6 +5387,11 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching
* (set/del PMKSA operations) in AP mode.
*
+ * @NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG: Driver supports per TID NoAck
+ * policy functionality.
+ * @NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG: Driver supports STA specific NoAck
+ * policy functionality.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5384,6 +5433,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+ NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG,
+ NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 82d5e1e..352eb4a2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -280,6 +280,13 @@ static int validate_ie_attr(const struct nlattr *attr,
NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
};
+static const struct nla_policy
+nl80211_attr_tid_config_policy[NL80211_ATTR_TID_CONFIG_MAX + 1] = {
+ [NL80211_ATTR_TID_CONFIG_TID] = NLA_POLICY_MAX(NLA_U8, 7),
+ [NL80211_ATTR_TID_CONFIG_NOACK] =
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
+};
+
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
@@ -541,6 +548,8 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_PEER_MEASUREMENTS] =
NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
[NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
+ [NL80211_ATTR_TID_CONFIG] =
+ NLA_POLICY_NESTED(nl80211_attr_tid_config_policy),
};
/* policy for the key attributes */
@@ -13241,6 +13250,91 @@ static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
return -ENOBUFS;
}
+static int parse_tid_conf(struct cfg80211_registered_device *rdev,
+ struct nlattr *attrs[],
+ struct ieee80211_tid_cfg *tid_conf,
+ const u8 *peer)
+{
+ tid_conf->tid = nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_TID]);
+ if (attrs[NL80211_ATTR_TID_CONFIG_NOACK]) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG))
+ return -ENOTSUPP;
+
+ if (peer && !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG))
+ return -ENOTSUPP;
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_NOACK;
+ tid_conf->noack =
+ nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_NOACK]);
+ }
+
+ return 0;
+}
+
+static int nl80211_set_tid_config(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct nlattr *attrs[NL80211_ATTR_TID_CONFIG_MAX + 1];
+ struct net_device *dev = info->user_ptr[1];
+ struct ieee80211_tid_config *tid_conf;
+ struct nlattr *tid;
+ int conf_idx = 0, rem_conf;
+ u32 num_conf = 0, size_of_conf;
+ int ret = -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_TID_CONFIG])
+ return -EINVAL;
+
+ if (!rdev->ops->set_tid_config)
+ return -EOPNOTSUPP;
+
+ nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
+ rem_conf)
+ num_conf++;
+
+ size_of_conf = sizeof(struct ieee80211_tid_config) +
+ num_conf * sizeof(struct ieee80211_tid_cfg);
+
+ tid_conf = kzalloc(size_of_conf, GFP_KERNEL);
+ if (!tid_conf)
+ return -ENOMEM;
+
+ tid_conf->n_tid_conf = num_conf;
+
+ if (info->attrs[NL80211_ATTR_MAC])
+ tid_conf->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ else
+ tid_conf->peer = NULL;
+
+ nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
+ rem_conf) {
+ ret = nla_parse_nested(attrs, NL80211_ATTR_TID_CONFIG_MAX, tid,
+ NULL, NULL);
+
+ if (ret)
+ return ret;
+
+ if (!attrs[NL80211_ATTR_TID_CONFIG_TID])
+ return -EINVAL;
+
+ ret = parse_tid_conf(rdev, attrs, &tid_conf->tid_conf[conf_idx],
+ tid_conf->peer);
+ if (ret)
+ goto bad_tid_conf;
+
+ conf_idx++;
+ }
+
+ return rdev_set_tid_config(rdev, dev, tid_conf);
+
+bad_tid_conf:
+ kfree(tid_conf);
+ return ret;
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -14175,6 +14269,14 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_SET_TID_CONFIG,
+ .doit = nl80211_set_tid_config,
+ .policy = nl80211_policy,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
static struct genl_family nl80211_fam __ro_after_init = {
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 5cb48d1..59e1905 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1272,4 +1272,15 @@ static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev,
trace_rdev_return_void(&rdev->wiphy);
}
+static inline int rdev_set_tid_config(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_tid_config *tid_conf)
+{
+ int ret;
+
+ trace_rdev_set_tid_config(&rdev->wiphy, dev, tid_conf);
+ ret = rdev->ops->set_tid_config(&rdev->wiphy, dev, tid_conf);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 44b2ce1..186de1f 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3362,6 +3362,24 @@
WIPHY_PR_ARG, WDEV_PR_ARG,
(unsigned long long)__entry->cookie)
);
+
+TRACE_EVENT(rdev_set_tid_config,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct ieee80211_tid_config *tid_conf),
+ TP_ARGS(wiphy, netdev, tid_conf),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, tid_conf->peer);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
--
1.9.1
^ permalink raw reply related
* [PATCHv2 2/9] nl80211: Add new netlink attribute for TID speicific retry count
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
This patch introduced below NL attributes to add support for
configuring data TID specific retry count
NL80211_ATTR_TID_CONFIG_RETRY
NL80211_ATTR_TID_CONFIG_RETRY_LONG
NL80211_ATTR_TID_CONFIG_RETRY_SHORT
These attributes are added in NL80211_ATTR_TID_CONFIG nested attribute.
This will be useful for the driver which supports data TID specific retry
count configuration rather using phy level retry configuration.
This TID specific retry configuration will have more precedence than
phy level configuration. This configuration can be applied for a
specific peer. To apply this configuration specific to a peer
rather than being applied for all the connected stations,
MAC address of the peer can be passed in NL80211_ATTR_MAC attribute.
Driver should advertise WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT and
max_data_retry_count value to notify user space to avoid of passing
greater than the allowed limit.
Driver supporting TID specific retry configuration should advertise
NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG and per STA specific
data TID retry configuration should advertise
NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 11 ++++++++++
include/uapi/linux/nl80211.h | 48 ++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 34 +++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 07eb2de..55c4ddf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -511,6 +511,7 @@ struct cfg80211_chan_def {
enum ieee80211_tid_conf_mask {
IEEE80211_TID_CONF_NOACK = BIT(0),
+ IEEE80211_TID_CONF_RETRY = BIT(1),
};
/**
@@ -519,11 +520,15 @@ enum ieee80211_tid_conf_mask {
* @tid_conf_mask: bitmap indicating which parameter changed
* see %enum ieee80211_tid_conf_mask
* @noack: noack configuration value for the TID
+ * @retry_long: retry count value
+ * @retry_short: retry count value
*/
struct ieee80211_tid_cfg {
u8 tid;
enum ieee80211_tid_conf_mask tid_conf_mask;
u8 noack;
+ int retry_long;
+ int retry_short;
};
/**
@@ -3832,6 +3837,7 @@ struct cfg80211_ops {
* beaconing mode (AP, IBSS, Mesh, ...).
* @WIPHY_FLAG_HAS_STATIC_WEP: The device supports static WEP key installation
* before connection.
+ * @WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT: Device supports data retry count call.
*/
enum wiphy_flags {
/* use hole at 0 */
@@ -3858,6 +3864,7 @@ enum wiphy_flags {
WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22),
WIPHY_FLAG_HAS_CHANNEL_SWITCH = BIT(23),
WIPHY_FLAG_HAS_STATIC_WEP = BIT(24),
+ WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT = BIT(25),
};
/**
@@ -4365,6 +4372,8 @@ struct cfg80211_pmsr_capabilities {
* @support_mbssid must be set for this to have any effect.
*
* @pmsr_capa: peer measurement capabilities
+ * @max_data_retry_count: Maximum limit can be configured as retry count
+ * for a TID.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -4509,6 +4518,8 @@ struct wiphy {
const struct cfg80211_pmsr_capabilities *pmsr_capa;
+ u8 max_data_retry_count;
+
char priv[0] __aligned(NETDEV_ALIGN);
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c901a48..f2ce845 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2316,6 +2316,8 @@ enum nl80211_commands {
*
* @NL80211_ATTR_TID_CONFIG: TID specific configuration in a
* nested attribute with %NL80211_ATTR_TID_* sub-attributes.
+ * @NL80211_ATTR_MAX_RETRY_COUNT: The upper limit for the retry count
+ * configuration that the driver can accept.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2769,6 +2771,7 @@ enum nl80211_attrs {
NL80211_ATTR_AIRTIME_WEIGHT,
NL80211_ATTR_TID_CONFIG,
+ NL80211_ATTR_MAX_RETRY_COUNT,
/* add attributes here, update the policy in nl80211.c */
@@ -4576,11 +4579,50 @@ enum nl80211_tid_config {
* advertise NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG and
* NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG for supporting per sta
* configuration.
+ * @NL80211_ATTR_TID_CONFIG_RETRY: Data TID retry count should be applied
+ * with the value passed through %NL80211_ATTR_TID_CONFIG_RETRY_LONG
+ * and/or %NL80211_ATTR_TID_CONFIG_RETRY_SHORT. This configuration
+ * is per-TID, and the TID is specified with %NL80211_ATTR_TID_CONFIG_TID.
+ * If the peer MAC address is passed in %NL80211_ATTR_MAC, the retry
+ * configuration is applied to the data frame for the tid to that
+ * connected station.
+ * This attribute will be useful to notfiy the driver to apply default
+ * retry values for the connected station (%NL80211_ATTR_MAC), when the
+ * command received without %NL80211_ATTR_RETRY_LONG and/or
+ * %NL80211_ATTR_RETRY_SHORT.
+ * Station specific retry configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, this configuration
+ * should be treated as per-netdev configuration. This configuration will
+ * be cleared when the interface goes down and on the disconnection from a
+ * BSS. When retry count has never been configured using this command, the
+ * other available radio level retry configuration
+ * (%NL80211_ATTR_WIPHY_RETRY_SHORT and %NL80211_ATTR_WIPHY_RETRY_LONG)
+ * should be used. Driver supporting this feature should advertise
+ * NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG and supporting per station
+ * retry count configuration should advertise
+ * NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG.
+ * @NL80211_ATTR_TID_CONFIG_RETRY_SHORT: Number of retries used with data frame
+ * transmission, user-space sets this configuration in
+ * &NL80211_CMD_SET_TID_CONFIG. It is u8 type, min value is 1 and
+ * the max value should be advertised by the driver through
+ * max_data_retry_count. when this attribute is not present, the driver
+ * would use the default configuration.
+ * @NL80211_ATTR_TID_CONFIG_RETRY_LONG: Number of retries used with data frame
+ * transmission, user-space sets this configuration in
+ * &NL80211_CMD_SET_TID_CONFIG. Its type is u8, min value is 1 and
+ * the max value should be advertised by the driver through
+ * max_data_retry_count. when this attribute is not present, the driver
+ * would use the default configuration.
*/
enum nl80211_attr_tid_config {
__NL80211_ATTR_TID_INVALID,
NL80211_ATTR_TID_CONFIG_TID,
NL80211_ATTR_TID_CONFIG_NOACK,
+ NL80211_ATTR_TID_CONFIG_RETRY,
+ NL80211_ATTR_TID_CONFIG_RETRY_SHORT,
+ NL80211_ATTR_TID_CONFIG_RETRY_LONG,
/* keep last */
__NL80211_ATTR_TID_CONFIG_AFTER_LAST,
@@ -5391,6 +5433,10 @@ enum nl80211_feature_flags {
* policy functionality.
* @NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG: Driver supports STA specific NoAck
* policy functionality.
+ * @NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG: Driver supports per TID data retry
+ * count functionality.
+ * @NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG: Driver supports STA specific
+ * data retry count functionality.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5435,6 +5481,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG,
NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG,
+ NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG,
+ NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 352eb4a2..998c9dc 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -285,6 +285,9 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_TID_CONFIG_TID] = NLA_POLICY_MAX(NLA_U8, 7),
[NL80211_ATTR_TID_CONFIG_NOACK] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
+ [NL80211_ATTR_TID_CONFIG_RETRY] = { .type = NLA_FLAG },
+ [NL80211_ATTR_TID_CONFIG_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
+ [NL80211_ATTR_TID_CONFIG_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
@@ -13270,6 +13273,37 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_NOACK]);
}
+ if (nla_get_flag(attrs[NL80211_ATTR_TID_CONFIG_RETRY])) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG))
+ return -ENOTSUPP;
+
+ if (peer && !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG))
+ return -ENOTSUPP;
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_RETRY;
+ if (attrs[NL80211_ATTR_TID_CONFIG_RETRY_SHORT]) {
+ tid_conf->retry_short =
+ nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_RETRY_SHORT]);
+ if (tid_conf->retry_short >
+ rdev->wiphy.max_data_retry_count)
+ return -EINVAL;
+ } else {
+ tid_conf->retry_short = -1;
+ }
+
+ if (attrs[NL80211_ATTR_TID_CONFIG_RETRY_LONG]) {
+ tid_conf->retry_long =
+ nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_RETRY_LONG]);
+ if (tid_conf->retry_long >
+ rdev->wiphy.max_data_retry_count)
+ return -EINVAL;
+ } else {
+ tid_conf->retry_long = -1;
+ }
+ }
+
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCHv2 3/9] nl80211: Add netlink attribute for AMPDU aggregation enable/disable
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
Introduce NL80211_ATTR_TID_CONFIG_AMPDU_CTRL in nl80211_attr_tid_config
to accept TID specific AMPDU aggregation enable/disable configuration
through NL80211_CMD_SET_TID_CONFIG command. TID for which the
aggregation control configuration is to be applied is passed in
NL80211_ATTR_TID_CONFIG_TID attribute. When the user-space wants this
configuration peer specific rather than being applied for all the
connected stations, MAC address of the peer can be passed in
NL80211_ATTR_MAC attribute.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL and supporting per-STA data TID
ampdu configuration should advertise NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 3 +++
include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++++
net/wireless/nl80211.c | 15 +++++++++++++++
3 files changed, 40 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 55c4ddf..fcf33c9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -512,6 +512,7 @@ struct cfg80211_chan_def {
enum ieee80211_tid_conf_mask {
IEEE80211_TID_CONF_NOACK = BIT(0),
IEEE80211_TID_CONF_RETRY = BIT(1),
+ IEEE80211_TID_CONF_AMPDU = BIT(2),
};
/**
@@ -522,6 +523,7 @@ enum ieee80211_tid_conf_mask {
* @noack: noack configuration value for the TID
* @retry_long: retry count value
* @retry_short: retry count value
+ * @ampdu: Enable/Disable aggregation
*/
struct ieee80211_tid_cfg {
u8 tid;
@@ -529,6 +531,7 @@ struct ieee80211_tid_cfg {
u8 noack;
int retry_long;
int retry_short;
+ u8 ampdu;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f2ce845..f94651d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4615,6 +4615,21 @@ enum nl80211_tid_config {
* the max value should be advertised by the driver through
* max_data_retry_count. when this attribute is not present, the driver
* would use the default configuration.
+ * @NL80211_ATTR_TID_CONFIG_AMPDU_CTRL: Enable/Disable aggregation for the TID
+ * specified in %%NL80211_ATTR_TID_CONFIG_TID. Its type is u8,
+ * if the peer MAC address is passed in %NL80211_ATTR_MAC, the aggregation
+ * configuration is applied
+ * to the data frame for the tid to that connected station.
+ * Station specific aggregation configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, this configuration
+ * should be treated as per-netdev configuration. This configuration will
+ * be cleared when the interface goes down and on the disconnection from a
+ * BSS. Driver supporting this feature should advertise
+ * NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL and supporting per station
+ * aggregation configuration should advertise
+ * NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL.
*/
enum nl80211_attr_tid_config {
__NL80211_ATTR_TID_INVALID,
@@ -4623,6 +4638,7 @@ enum nl80211_attr_tid_config {
NL80211_ATTR_TID_CONFIG_RETRY,
NL80211_ATTR_TID_CONFIG_RETRY_SHORT,
NL80211_ATTR_TID_CONFIG_RETRY_LONG,
+ NL80211_ATTR_TID_CONFIG_AMPDU_CTRL,
/* keep last */
__NL80211_ATTR_TID_CONFIG_AFTER_LAST,
@@ -5437,6 +5453,10 @@ enum nl80211_feature_flags {
* count functionality.
* @NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG: Driver supports STA specific
* data retry count functionality.
+ * @NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL: Driver supports TID specific
+ * aggregation control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL: Driver supports per STA
+ * specific TID aggregation control(enable/disable).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5483,6 +5503,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG,
NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG,
NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG,
+ NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL,
+ NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 998c9dc..d4a88fa 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -288,6 +288,8 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_TID_CONFIG_RETRY] = { .type = NLA_FLAG },
[NL80211_ATTR_TID_CONFIG_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
[NL80211_ATTR_TID_CONFIG_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
+ [NL80211_ATTR_TID_CONFIG_AMPDU_CTRL] =
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
@@ -13304,6 +13306,19 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
}
}
+ if (attrs[NL80211_ATTR_TID_CONFIG_AMPDU_CTRL]) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL))
+ return -ENOTSUPP;
+
+ if (peer && !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL))
+ return -ENOTSUPP;
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_AMPDU;
+ tid_conf->ampdu =
+ nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_AMPDU_CTRL]);
+ }
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCHv2 4/9] nl80211: Add netlink attribute to enable/disable RTS_CTS
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
Introduce NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL in nl80211_attr_tid_config
to accept TID specific RTS_CTS enable/disable configuration
through NL80211_CMD_SET_TID_CONFIG command. TID for which the
RTS_CTS control configuration is to be applied is passed in
NL80211_ATTR_TID_CONFIG_TID attribute. When the user-space wants this
configuration peer specific rather than being applied for all the
connected stations, MAC address of the peer can be passed in
NL80211_ATTR_MAC attribute.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL and supporting per-STA data TID
RTS_CTS configuration should advertise NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 3 +++
include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++++
net/wireless/nl80211.c | 17 +++++++++++++++++
3 files changed, 42 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fcf33c9..cf4a3f0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -513,6 +513,7 @@ enum ieee80211_tid_conf_mask {
IEEE80211_TID_CONF_NOACK = BIT(0),
IEEE80211_TID_CONF_RETRY = BIT(1),
IEEE80211_TID_CONF_AMPDU = BIT(2),
+ IEEE80211_TID_CONF_RTSCTS = BIT(3),
};
/**
@@ -524,6 +525,7 @@ enum ieee80211_tid_conf_mask {
* @retry_long: retry count value
* @retry_short: retry count value
* @ampdu: Enable/Disable aggregation
+ * @rtscts: Enable/Disable RTS/CTS
*/
struct ieee80211_tid_cfg {
u8 tid;
@@ -532,6 +534,7 @@ struct ieee80211_tid_cfg {
int retry_long;
int retry_short;
u8 ampdu;
+ u8 rtscts;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f94651d..996b4d4 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4630,6 +4630,21 @@ enum nl80211_tid_config {
* NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL and supporting per station
* aggregation configuration should advertise
* NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL.
+ * @NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TID
+ * specified in %%NL80211_ATTR_TID_CONFIG_TID. It is u8 type, if the
+ * peer MAC address is passed in %NL80211_ATTR_MAC, then this
+ * configuration is applied to the data frame for the tid to that
+ * connected station.
+ * Station specific RTS_CTS configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, this configuration
+ * should be treated as per-netdev configuration. This configuration will
+ * be cleared when the interface goes down and on the disconnection from a
+ * BSS. Driver supporting this feature should advertise
+ * NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL and supporting per station
+ * RTS_CTS configuration should advertise
+ * NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL.
*/
enum nl80211_attr_tid_config {
__NL80211_ATTR_TID_INVALID,
@@ -4639,6 +4654,7 @@ enum nl80211_attr_tid_config {
NL80211_ATTR_TID_CONFIG_RETRY_SHORT,
NL80211_ATTR_TID_CONFIG_RETRY_LONG,
NL80211_ATTR_TID_CONFIG_AMPDU_CTRL,
+ NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL,
/* keep last */
__NL80211_ATTR_TID_CONFIG_AFTER_LAST,
@@ -5457,6 +5473,10 @@ enum nl80211_feature_flags {
* aggregation control(enable/disable).
* @NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL: Driver supports per STA
* specific TID aggregation control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL: Driver supports TID specific
+ * RTS_CTS control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL: Driver supports STA specific
+ * RTS_CTS control(enable/disable).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5505,6 +5525,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG,
NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL,
NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL,
+ NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL,
+ NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d4a88fa..cd1e1e8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -290,6 +290,8 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_ATTR_TID_CONFIG_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
[NL80211_ATTR_TID_CONFIG_AMPDU_CTRL] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
+ [NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL] =
+ NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
@@ -13319,6 +13321,21 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
tid_conf->ampdu =
nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_AMPDU_CTRL]);
}
+
+ if (attrs[NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL]) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL))
+ return -ENOTSUPP;
+
+ if (peer && !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL))
+ return -ENOTSUPP;
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_RTSCTS;
+ tid_conf->rtscts =
+ nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL]);
+ }
+
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCHv2 5/9] nl80211: Add netlink attribute to configure TID specific tx rate
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
Introduce NL80211_ATTR_TID_CONFIG_TX_RATES in nl80211_attr_tid_config
to accept data TID specific TX bitrate configuration
through NL80211_CMD_SET_TID_CONFIG command. TID for which the
this configuration is to be applied is passed in
NL80211_ATTR_TID_CONFIG_TID attribute. TX bitrate mask values passed
in NL80211_ATTR_TX_RATES attribute and NL80211_ATTR_TID_CONFIG_TX_RATES
attribute will have types of the TX rate should be applied.
When the user-space wants this configuration peer specific
rather than being applied for all the connected stations,
MAC address of the peer can be passed in NL80211_ATTR_MAC attribute.
NL80211_ATTR_TX_RATES attribute can hold single value at a time, so the
TX bitrate configuration can be set one TID at a time.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK and supporting per-STA data TID
TX bitrate configuration should advertise
NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/cfg80211.h | 5 +++++
include/uapi/linux/nl80211.h | 38 ++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 41 +++++++++++++++++++++++++++++++++++++++--
3 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index cf4a3f0..713de1e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -514,6 +514,7 @@ enum ieee80211_tid_conf_mask {
IEEE80211_TID_CONF_RETRY = BIT(1),
IEEE80211_TID_CONF_AMPDU = BIT(2),
IEEE80211_TID_CONF_RTSCTS = BIT(3),
+ IEEE80211_TID_CONF_TX_BITRATE = BIT(4),
};
/**
@@ -526,6 +527,8 @@ enum ieee80211_tid_conf_mask {
* @retry_short: retry count value
* @ampdu: Enable/Disable aggregation
* @rtscts: Enable/Disable RTS/CTS
+ * @txrate_type: TX bitrate mask type
+ * @mask: bitrate to be applied for the TID
*/
struct ieee80211_tid_cfg {
u8 tid;
@@ -535,6 +538,8 @@ struct ieee80211_tid_cfg {
int retry_short;
u8 ampdu;
u8 rtscts;
+ enum nl80211_tx_rate_setting txrate_type;
+ struct cfg80211_bitrate_mask *mask;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 996b4d4..9a6f63e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4557,6 +4557,18 @@ enum nl80211_tx_power_setting {
NL80211_TX_POWER_FIXED,
};
+/**
+ * enum nl80211_tx_rate_setting - TX rate configuration type
+ * @NL80211_TX_RATE_AUTOMATIC: automatically determine TX rate
+ * @NL80211_TX_RATE_LIMITED: limit the TX rate by the TX rate parameter
+ * @NL80211_TX_RATE_FIXED: fix TX rate to the TX rate parameter
+ */
+enum nl80211_tx_rate_setting {
+ NL80211_TX_RATE_AUTOMATIC,
+ NL80211_TX_RATE_LIMITED,
+ NL80211_TX_RATE_FIXED,
+};
+
enum nl80211_tid_config {
NL80211_TID_CONFIG_DEFAULT,
NL80211_TID_CONFIG_ENABLE,
@@ -4645,6 +4657,25 @@ enum nl80211_tid_config {
* NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL and supporting per station
* RTS_CTS configuration should advertise
* NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL.
+ * @NL80211_ATTR_TID_CONFIG_TX_RATES: Data frame TX rate mask should be applied
+ * with the parameters passed through %NL80211_ATTR_TX_RATES. This
+ * configuration is per TID, TID is specified with
+ * %NL80211_ATTR_TID_CONFIG_TID.
+ * If the peer MAC address is passed in %NL80211_ATTR_MAC, then this
+ * configuration is applied to the data frame for the tid to that connected
+ * station. This attribute will be useful to notfiy the driver that what
+ * type of txrate should be applied(%enum enum nl80211_tx_rate_setting)
+ * for the connected station (%NL80211_ATTR_MAC),
+ * Station specific retry configuration is valid only for STA's
+ * current connection. i.e. the configuration will be reset to default when
+ * the station connects back after disconnection/roaming.
+ * when user-space does not include %NL80211_ATTR_MAC, this configuration
+ * should be treated as per-netdev configuration. This configuration will
+ * be cleared when the interface goes down and on the disconnection from a
+ * BSS. Driver supporting this feature should advertise
+ * NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK and supporting per station
+ * TX bitrate configuration should advertise
+ * NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK.
*/
enum nl80211_attr_tid_config {
__NL80211_ATTR_TID_INVALID,
@@ -4655,6 +4686,7 @@ enum nl80211_attr_tid_config {
NL80211_ATTR_TID_CONFIG_RETRY_LONG,
NL80211_ATTR_TID_CONFIG_AMPDU_CTRL,
NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL,
+ NL80211_ATTR_TID_CONFIG_TX_RATES,
/* keep last */
__NL80211_ATTR_TID_CONFIG_AFTER_LAST,
@@ -5477,6 +5509,10 @@ enum nl80211_feature_flags {
* RTS_CTS control(enable/disable).
* @NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL: Driver supports STA specific
* RTS_CTS control(enable/disable).
+ * @NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK: Driver supports TID specific
+ * TX bitrate configuration.
+ * @NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK: Driver supports STA specific
+ * TX bitrate configuration.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5527,6 +5563,8 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL,
NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL,
NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL,
+ NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK,
+ NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cd1e1e8..25ed505 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -292,6 +292,8 @@ static int validate_ie_attr(const struct nlattr *attr,
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
[NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
+ [NL80211_ATTR_TID_CONFIG_TX_RATES] =
+ NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
@@ -13260,8 +13262,10 @@ static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
static int parse_tid_conf(struct cfg80211_registered_device *rdev,
struct nlattr *attrs[],
struct ieee80211_tid_cfg *tid_conf,
- const u8 *peer)
+ struct genl_info *info, const u8 *peer)
{
+ int ret;
+
tid_conf->tid = nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_TID]);
if (attrs[NL80211_ATTR_TID_CONFIG_NOACK]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
@@ -13336,6 +13340,39 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL]);
}
+ if (attrs[NL80211_ATTR_TID_CONFIG_TX_RATES]) {
+ int idx;
+
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK))
+ return -EOPNOTSUPP;
+
+ if (peer &&
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK))
+ return -EOPNOTSUPP;
+
+ idx = NL80211_ATTR_TID_CONFIG_TX_RATES;
+ tid_conf->txrate_type = nla_get_u8(attrs[idx]);
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_TX_BITRATE;
+ if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
+ tid_conf->mask =
+ kzalloc(sizeof(struct cfg80211_bitrate_mask),
+ GFP_KERNEL);
+ if (!tid_conf->mask)
+ return -ENOMEM;
+ ret = nl80211_parse_tx_bitrate_mask(info,
+ tid_conf->mask);
+ if (ret) {
+ kfree(tid_conf->mask);
+ return ret;
+ }
+ } else {
+ tid_conf->mask = NULL;
+ }
+ }
+
return 0;
}
@@ -13387,7 +13424,7 @@ static int nl80211_set_tid_config(struct sk_buff *skb,
return -EINVAL;
ret = parse_tid_conf(rdev, attrs, &tid_conf->tid_conf[conf_idx],
- tid_conf->peer);
+ info, tid_conf->peer);
if (ret)
goto bad_tid_conf;
--
1.9.1
^ permalink raw reply related
* [PATCHv2 6/9] mac80211: Add api to support configuring TID specific configuration
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
Implement drv_set_tid_config api to allow TID specific
configuration. This per-TID configuration
will be applied for all the connected stations when MAC is NULL.
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
include/net/mac80211.h | 35 +++++++++++++++++++++++++++++++++++
net/mac80211/cfg.c | 28 ++++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 15 +++++++++++++++
3 files changed, 78 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 97aed7b..dda30e9a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1552,6 +1552,8 @@ enum ieee80211_vif_flags {
IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
};
+#define IEEE80211_TID_MAX 8
+
/**
* struct ieee80211_vif - per-interface data
*
@@ -1589,6 +1591,11 @@ enum ieee80211_vif_flags {
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
* protected by fq->lock.
+ * @noack: per-TID noack policy.
+ * @retry_short: per-TID retry count.
+ * @retry_long: per-TID count.
+ * @ampdu: per-TID Aggregation-MPDU.
+ * @tx_rate_mask: per-TID tx rate value.
*/
struct ieee80211_vif {
enum nl80211_iftype type;
@@ -1615,6 +1622,14 @@ struct ieee80211_vif {
bool txqs_stopped[IEEE80211_NUM_ACS];
+ u8 noack[IEEE80211_TID_MAX];
+ int retry_short[IEEE80211_TID_MAX];
+ int retry_long[IEEE80211_TID_MAX];
+ u8 ampdu[IEEE80211_TID_MAX];
+ u8 rate_ctrl[IEEE80211_TID_MAX];
+ u32 rate_code[IEEE80211_TID_MAX];
+ u8 rtscts[IEEE80211_TID_MAX];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -1929,6 +1944,11 @@ struct ieee80211_sta_rates {
* @max_tid_amsdu_len: Maximum A-MSDU size in bytes for this TID
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
* the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
+ * @noack: per-TID noack policy.
+ * @retry_short: per-TID retry count.
+ * @retry_long: per-TID count.
+ * @ampdu: per-TID Aggregation-MPDU.
+ * @tx_rate_mask: per-TID tx rate value.
*/
struct ieee80211_sta {
u32 supp_rates[NUM_NL80211_BANDS];
@@ -1972,6 +1992,13 @@ struct ieee80211_sta {
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];
+ u8 noack[IEEE80211_TID_MAX];
+ int retry_short[IEEE80211_TID_MAX];
+ int retry_long[IEEE80211_TID_MAX];
+ u8 ampdu[IEEE80211_TID_MAX];
+ u8 rate_ctrl[IEEE80211_TID_MAX];
+ u8 rtscts[IEEE80211_TID_MAX];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -3698,6 +3725,10 @@ enum ieee80211_reconfig_type {
*
* @start_pmsr: start peer measurement (e.g. FTM) (this call can sleep)
* @abort_pmsr: abort peer measurement (this call can sleep)
+ * @set_tid_config: TID specific configurations will be applied for a particular
+ * station when @sta is non-NULL. When @sta is NULL, then the configuration
+ * will be for all the connected clients in the vif.
+ * This callback may sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3990,6 +4021,10 @@ struct ieee80211_ops {
struct cfg80211_pmsr_request *request);
void (*abort_pmsr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request);
+ int (*set_tid_config)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tid_config *tid_conf);
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 09dd1c2..7d9c44d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3893,6 +3893,33 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
return drv_abort_pmsr(local, sdata, request);
}
+static int ieee80211_set_tid_config(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_tid_config *tid_conf)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct sta_info *sta;
+ int ret;
+
+ if (!sdata->local->ops->set_tid_config)
+ return -EOPNOTSUPP;
+
+ if (!tid_conf->peer)
+ return drv_set_tid_config(sdata->local, sdata, NULL, tid_conf);
+
+ mutex_lock(&sdata->local->sta_mtx);
+
+ sta = sta_info_get_bss(sdata, tid_conf->peer);
+ if (!sta) {
+ mutex_unlock(&sdata->local->sta_mtx);
+ return -ENOENT;
+ }
+
+ ret = drv_set_tid_config(sdata->local, sdata, &sta->sta, tid_conf);
+ mutex_unlock(&sdata->local->sta_mtx);
+ return ret;
+}
+
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3990,4 +4017,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
.get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
.start_pmsr = ieee80211_start_pmsr,
.abort_pmsr = ieee80211_abort_pmsr,
+ .set_tid_config = ieee80211_set_tid_config,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index ba3c07b..082d81b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1319,4 +1319,19 @@ static inline void drv_del_nan_func(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+static inline int drv_set_tid_config(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tid_config *tid_conf)
+{
+ int ret;
+
+ might_sleep();
+ ret = local->ops->set_tid_config(&local->hw, &sdata->vif, sta,
+ tid_conf);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
#endif /* __MAC80211_DRIVER_OPS */
--
1.9.1
^ permalink raw reply related
* [PATCHv2 7/9] ath10k: Add wmi command support for station specific TID config
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
This patch adds WMI interface to configure station specific
TID configuration . Host needs to send station's MAC address
along with TID number and its configuration to target through
WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID.
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT flag is added to advertise
this support.
Testing:
* Tested HW: QCA9888
* Tested FW: 10.4-3.5.1-00052
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/wmi-ops.h | 19 +++++++++++
drivers/net/wireless/ath/ath10k/wmi.c | 32 +++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.h | 52 +++++++++++++++++++++++++++++++
3 files changed, 103 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 1491c25..796badf 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -216,6 +216,8 @@ struct wmi_ops {
struct sk_buff *(*gen_bb_timing)
(struct ath10k *ar,
const struct wmi_bb_timing_cfg_arg *arg);
+ struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar,
+ const struct wmi_per_peer_per_tid_cfg_arg *arg);
};
@@ -1616,4 +1618,21 @@ struct wmi_ops {
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->set_bb_timing_cmdid);
}
+
+static inline int
+ath10k_wmi_set_per_peer_per_tid_cfg(struct ath10k *ar,
+ const struct wmi_per_peer_per_tid_cfg_arg *arg)
+{
+ struct sk_buff *skb;
+
+ if (!ar->wmi.ops->gen_per_peer_per_tid_cfg)
+ return -EOPNOTSUPP;
+
+ skb = ar->wmi.ops->gen_per_peer_per_tid_cfg(ar, arg);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ return ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->per_peer_per_tid_config_cmdid);
+}
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 97e5b2e..44b66f2 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -740,6 +740,7 @@
.tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID,
.tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
.radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
+ .per_peer_per_tid_config_cmdid = WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID,
};
/* MAIN WMI VDEV param map */
@@ -8862,6 +8863,36 @@ static u32 ath10k_wmi_prepare_peer_qos(u8 uapsd_queues, u8 sp)
}
static struct sk_buff *
+ath10k_wmi_10_4_gen_per_peer_per_tid_cfg(struct ath10k *ar,
+ const struct wmi_per_peer_per_tid_cfg_arg *arg)
+{
+ struct wmi_peer_per_tid_cfg_cmd *cmd;
+ struct sk_buff *skb;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ memset(skb->data, 0, sizeof(*cmd));
+
+ cmd = (struct wmi_peer_per_tid_cfg_cmd *)skb->data;
+ cmd->vdev_id = cpu_to_le32(arg->vdev_id);
+ ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_macaddr.addr);
+ cmd->tid = cpu_to_le32(arg->tid);
+ cmd->ack_policy = cpu_to_le32(arg->ack_policy);
+ cmd->aggr_control = cpu_to_le32(arg->aggr_control);
+ cmd->rate_control = cpu_to_le32(arg->rate_ctrl);
+ cmd->retry_count = cpu_to_le32(arg->retry_count);
+ cmd->rcode_flags = cpu_to_le32(arg->rcode_flags);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d mac_addr %pM\n",
+ arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control, arg->rate_ctrl,
+ arg->rcode_flags, arg->retry_count, arg->peer_macaddr.addr);
+ return skb;
+}
+
+static struct sk_buff *
ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value)
{
struct wmi_echo_cmd *cmd;
@@ -9270,6 +9301,7 @@ static u32 ath10k_wmi_prepare_peer_qos(u8 uapsd_queues, u8 sp)
.gen_pdev_get_tpc_table_cmdid =
ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
.gen_radar_found = ath10k_wmi_10_4_gen_radar_found,
+ .gen_per_peer_per_tid_cfg = ath10k_wmi_10_4_gen_per_peer_per_tid_cfg,
/* shared with 10.2 */
.pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index d9b646f..187c13e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -200,6 +200,7 @@ enum wmi_service {
WMI_SERVICE_RTT_RESPONDER_ROLE,
WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
WMI_SERVICE_REPORT_AIRTIME,
+ WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT,
/* Remember to add the new value to wmi_service_name()! */
@@ -491,6 +492,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE);
SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
+ SVCSTR(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT);
case WMI_SERVICE_MAX:
return NULL;
@@ -818,6 +820,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME,
WMI_SERVICE_REPORT_AIRTIME, len);
+ SVCMAP(WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
}
#undef SVCMAP
@@ -1019,6 +1023,7 @@ struct wmi_cmd_map {
u32 tdls_set_offchan_mode_cmdid;
u32 radar_found_cmdid;
u32 set_bb_timing_cmdid;
+ u32 per_peer_per_tid_config_cmdid;
};
/*
@@ -1860,6 +1865,8 @@ enum wmi_10_4_cmd_id {
WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID,
WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID,
WMI_10_4_RADAR_FOUND_CMDID,
+ WMI_10_4_PEER_CFR_CAPTURE_CMDID,
+ WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID,
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
};
@@ -7145,6 +7152,51 @@ struct wmi_tdls_peer_event {
__le32 vdev_id;
} __packed;
+enum wmi_tid_aggr_control_conf {
+ WMI_TID_CONFIG_AGGR_CONTROL_IGNORE,
+ WMI_TID_CONFIG_AGGR_CONTROL_ENABLE,
+ WMI_TID_CONFIG_AGGR_CONTROL_DISABLE,
+};
+
+enum wmi_noack_tid_conf {
+ WMI_NOACK_TID_CONFIG_IGNORE_ACK_POLICY,
+ WMI_PEER_TID_CONFIG_ACK,
+ WMI_PEER_TID_CONFIG_NOACK,
+};
+
+enum wmi_tid_rate_ctrl_conf {
+ WMI_TID_CONFIG_RATE_CONTROL_IGNORE,
+ WMI_TID_CONFIG_RATE_CONTROL_AUTO,
+ WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE,
+ WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE,
+};
+
+struct wmi_per_peer_per_tid_cfg_arg {
+ u32 vdev_id;
+ struct wmi_mac_addr peer_macaddr;
+ u32 tid;
+ enum wmi_noack_tid_conf ack_policy;
+ enum wmi_tid_aggr_control_conf aggr_control;
+ u8 rate_ctrl;
+ u32 retry_count;
+ u32 rcode_flags;
+};
+
+struct wmi_peer_per_tid_cfg_cmd {
+ __le32 vdev_id;
+ struct wmi_mac_addr peer_macaddr;
+ __le32 tid;
+
+ /* see enum wmi_noack_tid_conf */
+ __le32 ack_policy;
+ /* see enum wmi_tid_aggr_control_conf */
+ __le32 aggr_control;
+ /* see enum wmi_tid_rate_ctrl_conf */
+ __le32 rate_control;
+ __le32 rcode_flags;
+ __le32 retry_count;
+} __packed;
+
enum wmi_txbf_conf {
WMI_TXBF_CONF_UNSUPPORTED,
WMI_TXBF_CONF_BEFORE_ASSOC,
--
1.9.1
^ permalink raw reply related
* [PATCHv2 8/9] ath10k: Add new api to support TID specific configuration
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
This patch add ops for set_tid_config to support TID
specific configuration. STA information along with the
TID config change mask to notify driver that which configuration
needs to be applied for this current command.
If the STA info not available in the command then the
configuration will be applied for all connected stations
in the vif. TID specific noack configuration requires
aggregation disabled and rate for the data TID packets
should be basic rates. So, if the TID already configured
with noack policy then driver will ignore the aggregation
or TX rate related configuration for the same data TID.
In TX rate configuration should be applied with highest
preamble configuration(HT rates should not be applied
for the station which supports vht rates).
Vif specific TID configuration will be applied for all
the connected stations except for the station which
already applied with the same configuration for the TID
through station specific command. Newly connecting stations
will be applied with vif TID configuration which will be stored
in ieee80211_vif.
Testing:
* Tested HW: QCA9888
* Tested FW: 10.4-3.5.1-00052
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/core.h | 7 +
drivers/net/wireless/ath/ath10k/mac.c | 602 ++++++++++++++++++++++++++++-----
2 files changed, 529 insertions(+), 80 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 27ec555..c25c426 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -82,6 +82,9 @@
/* Default Airtime weight multipler (Tuned for multiclient performance) */
#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4
+#define ATH10K_MAX_RETRY_COUNT 30
+#define ATH10K_MAX_TIDS 8
+
struct ath10k;
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -504,6 +507,7 @@ struct ath10k_sta {
#endif
/* Protected with ar->data_lock */
u32 peer_ps_state;
+ struct work_struct tid_config_wk;
};
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
@@ -571,6 +575,9 @@ struct ath10k_vif {
struct work_struct ap_csa_work;
struct delayed_work connection_loss_work;
struct cfg80211_bitrate_mask bitrate_mask;
+ u32 tid_conf_changed[ATH10K_MAX_TIDS];
+
+ struct ieee80211_tid_config *tid_config;
};
struct ath10k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b73c23d..5ba399f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2930,6 +2930,58 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
cancel_delayed_work_sync(&arvif->connection_loss_work);
}
+static int ath10k_new_peer_tid_config(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ struct ath10k_vif *arvif)
+{
+ struct wmi_per_peer_per_tid_cfg_arg arg = {};
+ struct ieee80211_vif *vif = arvif->vif;
+ bool config_apply;
+ int ret, i;
+
+ for (i = 0; i < ATH10K_MAX_TIDS; i++) {
+ config_apply = false;
+ if (vif->retry_long[i] || vif->ampdu[i] ||
+ vif->rate_code[i]) {
+ config_apply = true;
+ arg.tid = i;
+ arg.vdev_id = arvif->vdev_id;
+ arg.retry_count = vif->retry_long[i];
+ arg.aggr_control = vif->ampdu[i];
+ arg.rate_ctrl = vif->rate_ctrl[i];
+ arg.rcode_flags = vif->rate_code[i];
+ }
+
+ if (vif->noack[i]) {
+ arg.ack_policy = vif->noack[i];
+ arg.rate_ctrl =
+ WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE;
+ arg.aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
+ config_apply = true;
+ }
+
+ /* Assign default value(-1) to newly connected station.
+ * This is to identify station specific tid configuration not
+ * configured for the station.
+ */
+ sta->retry_long[i] = -1;
+ sta->noack[i] = -1;
+
+ if (!config_apply)
+ continue;
+
+ ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
+ ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
+ if (ret) {
+ ath10k_warn(ar, "failed to set per tid retry/aggr config for sta %pM: %d\n",
+ sta->addr, ret);
+ return ret;
+ }
+ memset(&arg, 0, sizeof(arg));
+ }
+ return 0;
+}
+
static int ath10k_station_assoc(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -2995,7 +3047,10 @@ static int ath10k_station_assoc(struct ath10k *ar,
}
}
- return ret;
+ if (!test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map))
+ return ret;
+
+ return ath10k_new_peer_tid_config(ar, sta, arvif);
}
static int ath10k_station_disassoc(struct ath10k *ar,
@@ -6350,6 +6405,332 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif,
ar->num_stations--;
}
+struct ath10k_mac_iter_tid_conf_data {
+ struct ieee80211_vif *curr_vif;
+ struct ath10k *ar;
+};
+
+static bool
+ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ int num_rates = 0;
+ int i;
+
+ num_rates += hweight32(mask->control[band].legacy);
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
+ num_rates += hweight8(mask->control[band].ht_mcs[i]);
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
+ num_rates += hweight16(mask->control[band].vht_mcs[i]);
+
+ return num_rates == 1;
+}
+
+static int
+ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask,
+ u8 *rate, u8 *nss)
+{
+ int rate_idx;
+ int i;
+ u16 bitrate;
+ u8 preamble;
+ u8 hw_rate;
+
+ if (hweight32(mask->control[band].legacy) == 1) {
+ rate_idx = ffs(mask->control[band].legacy) - 1;
+
+ if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
+ rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
+
+ hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
+ bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
+
+ if (ath10k_mac_bitrate_is_cck(bitrate))
+ preamble = WMI_RATE_PREAMBLE_CCK;
+ else
+ preamble = WMI_RATE_PREAMBLE_OFDM;
+
+ *nss = 1;
+ *rate = preamble << 6 |
+ (*nss - 1) << 4 |
+ hw_rate << 0;
+
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
+ if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
+ *nss = i + 1;
+ *rate = WMI_RATE_PREAMBLE_HT << 6 |
+ (*nss - 1) << 4 |
+ (ffs(mask->control[band].ht_mcs[i]) - 1);
+
+ return 0;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
+ if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
+ *nss = i + 1;
+ *rate = WMI_RATE_PREAMBLE_VHT << 6 |
+ (*nss - 1) << 4 |
+ (ffs(mask->control[band].vht_mcs[i]) - 1);
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ u32 rate_ctrl_flag)
+{
+ if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
+ if (!sta->vht_cap.vht_supported) {
+ ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
+ sta->addr);
+ return -EINVAL;
+ }
+ } else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
+ if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
+ ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
+ sta->addr);
+ return -EINVAL;
+ }
+ } else {
+ if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+ath10k_mac_tid_bitrate_config(struct ath10k *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u32 *rate_ctrl_flag, u8 *rate_ctrl,
+ enum nl80211_tx_rate_setting txrate_type,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct cfg80211_chan_def def;
+ enum nl80211_band band;
+ u8 nss, rate;
+ int ret;
+
+ if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
+ return -EINVAL;
+
+ if (txrate_type == NL80211_TX_RATE_AUTOMATIC) {
+ *rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO;
+ *rate_ctrl_flag = 0;
+ return 0;
+ }
+
+ band = def.chan->band;
+
+ if (!ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask))
+ return -EINVAL;
+
+ ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
+ &rate, &nss);
+ if (ret) {
+ ath10k_warn(ar, "failed to get single rate: %d\n",
+ ret);
+ return ret;
+ }
+ *rate_ctrl_flag = rate;
+
+ if (nss > sta->rx_nss) {
+ ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
+ nss, sta->rx_nss);
+ return -EINVAL;
+ }
+
+ if (ath10k_mac_validate_rate_mask(ar, sta, *rate_ctrl_flag))
+ return -EINVAL;
+
+ if (txrate_type == NL80211_TX_RATE_FIXED)
+ *rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE;
+ else
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+static void
+ath10k_mac_parse_tid_config(struct ath10k *ar,
+ struct ieee80211_sta *sta,
+ struct ieee80211_vif *vif,
+ struct ieee80211_tid_cfg *tid_conf,
+ struct wmi_per_peer_per_tid_cfg_arg *arg)
+{
+ u8 changed = tid_conf->tid_conf_mask;
+ int ret;
+
+ arg->tid = tid_conf->tid;
+
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ if (tid_conf->noack) {
+ arg->ack_policy = WMI_PEER_TID_CONFIG_NOACK;
+ arg->rate_ctrl =
+ WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE;
+ arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
+ } else {
+ arg->ack_policy = WMI_PEER_TID_CONFIG_ACK;
+ arg->rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO;
+ arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_ENABLE;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (tid_conf->retry_long == -1) {
+ if (vif->retry_long[arg->tid])
+ arg->retry_count = vif->retry_long[arg->tid];
+ else
+ arg->retry_count = ATH10K_MAX_RETRY_COUNT;
+ } else {
+ arg->retry_count = tid_conf->retry_long;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (tid_conf->ampdu) {
+ arg->aggr_control = tid_conf->ampdu;
+ } else {
+ if (vif->ampdu[arg->tid])
+ arg->aggr_control = vif->ampdu[arg->tid];
+ else
+ arg->aggr_control =
+ WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ ret = ath10k_mac_tid_bitrate_config(ar, vif, sta,
+ &arg->rcode_flags,
+ &arg->rate_ctrl,
+ tid_conf->txrate_type,
+ tid_conf->mask);
+ if (ret) {
+ ath10k_warn(ar, "failed to configure bitrate mask %d\n",
+ ret);
+ arg->rcode_flags = 0;
+ arg->rate_ctrl = 0;
+ }
+ }
+}
+
+static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
+{
+ struct wmi_per_peer_per_tid_cfg_arg arg = {};
+ struct ieee80211_vif *vif;
+ struct ieee80211_sta *sta;
+ struct ath10k_sta *arsta;
+ struct ath10k_vif *arvif;
+ struct ath10k *ar;
+ bool config_apply;
+ int ret, i;
+ u8 changed;
+
+ arsta = container_of(wk, struct ath10k_sta, tid_config_wk);
+ sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
+ arvif = arsta->arvif;
+ vif = arvif->vif;
+ ar = arvif->ar;
+
+ mutex_lock(&ar->conf_mutex);
+
+ ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
+ for (i = 0; i < ATH10K_MAX_TIDS; i++) {
+ config_apply = false;
+ changed = arvif->tid_conf_changed[i];
+
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ if (sta->noack[i] != -1) {
+ arg.ack_policy = 0;
+ } else {
+ config_apply = true;
+ arg.ack_policy = vif->noack[i];
+ arg.aggr_control = vif->ampdu[i];
+ arg.rate_ctrl = vif->rate_ctrl[i];
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (sta->retry_long[i] != -1 ||
+ sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.retry_count = 0;
+ } else {
+ arg.retry_count = vif->retry_long[i];
+ config_apply = true;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (sta->ampdu[i] ||
+ sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.aggr_control = 0;
+ } else {
+ arg.aggr_control = vif->ampdu[i];
+ config_apply = true;
+ }
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ if (sta->rate_ctrl[i] >
+ WMI_TID_CONFIG_RATE_CONTROL_AUTO ||
+ sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ } else {
+ arg.rate_ctrl = vif->rate_ctrl[i];
+ arg.rcode_flags = vif->rate_code[i];
+ config_apply = true;
+ }
+ }
+
+ arg.tid = i;
+
+ if (config_apply) {
+ ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
+ if (ret)
+ ath10k_warn(ar, "failed to set per tid config for sta %pM: %d\n",
+ sta->addr, ret);
+ }
+
+ arg.ack_policy = 0;
+ arg.retry_count = 0;
+ arg.aggr_control = 0;
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+
+ mutex_unlock(&ar->conf_mutex);
+}
+
+static void ath10k_mac_vif_stations_tid_conf(void *data,
+ struct ieee80211_sta *sta)
+{
+ struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ struct ath10k_mac_iter_tid_conf_data *iter_data = data;
+ struct ieee80211_vif *sta_vif = arsta->arvif->vif;
+
+ if (sta_vif != iter_data->curr_vif || !sta->wme)
+ return;
+
+ ieee80211_queue_work(iter_data->ar->hw, &arsta->tid_config_wk);
+}
+
static int ath10k_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -6369,6 +6750,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
arsta->arvif = arvif;
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);
+ INIT_WORK(&arsta->tid_config_wk, ath10k_sta_tid_cfg_wk);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
ath10k_mac_txq_init(sta->txq[i]);
@@ -6376,8 +6758,10 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
/* cancel must be done outside the mutex to avoid deadlock */
if ((old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST))
+ new_state == IEEE80211_STA_NOTEXIST)) {
cancel_work_sync(&arsta->update_wk);
+ cancel_work_sync(&arsta->tid_config_wk);
+ }
mutex_lock(&ar->conf_mutex);
@@ -7097,25 +7481,6 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
}
static bool
-ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask)
-{
- int num_rates = 0;
- int i;
-
- num_rates += hweight32(mask->control[band].legacy);
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
- num_rates += hweight8(mask->control[band].ht_mcs[i]);
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
- num_rates += hweight16(mask->control[band].vht_mcs[i]);
-
- return num_rates == 1;
-}
-
-static bool
ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
@@ -7164,65 +7529,6 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
return true;
}
-static int
-ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask,
- u8 *rate, u8 *nss)
-{
- int rate_idx;
- int i;
- u16 bitrate;
- u8 preamble;
- u8 hw_rate;
-
- if (hweight32(mask->control[band].legacy) == 1) {
- rate_idx = ffs(mask->control[band].legacy) - 1;
-
- if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
- rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
-
- hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
- bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
-
- if (ath10k_mac_bitrate_is_cck(bitrate))
- preamble = WMI_RATE_PREAMBLE_CCK;
- else
- preamble = WMI_RATE_PREAMBLE_OFDM;
-
- *nss = 1;
- *rate = preamble << 6 |
- (*nss - 1) << 4 |
- hw_rate << 0;
-
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
- if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
- *nss = i + 1;
- *rate = WMI_RATE_PREAMBLE_HT << 6 |
- (*nss - 1) << 4 |
- (ffs(mask->control[band].ht_mcs[i]) - 1);
-
- return 0;
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
- if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
- *nss = i + 1;
- *rate = WMI_RATE_PREAMBLE_VHT << 6 |
- (*nss - 1) << 4 |
- (ffs(mask->control[band].vht_mcs[i]) - 1);
-
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
u8 rate, u8 nss, u8 sgi, u8 ldpc)
{
@@ -7991,6 +8297,118 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
+static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tid_config *tid_config)
+{
+ struct ath10k *ar = hw->priv;
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
+ struct ath10k_mac_iter_tid_conf_data data = {};
+ struct wmi_per_peer_per_tid_cfg_arg arg = {};
+ int ret, i;
+ u8 changed;
+
+ mutex_lock(&ar->conf_mutex);
+ arg.vdev_id = arvif->vdev_id;
+
+ memset(arvif->tid_conf_changed, 0, sizeof(arvif->tid_conf_changed));
+
+ for (i = 0; i < tid_config->n_tid_conf; i++) {
+ ath10k_mac_parse_tid_config(ar, sta, vif,
+ &tid_config->tid_conf[i],
+ &arg);
+ changed = tid_config->tid_conf[i].tid_conf_mask;
+ if (sta) {
+ if (!sta->wme) {
+ ret = -ENOTSUPP;
+ goto exit;
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ if (sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK)
+ arg.retry_count = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ if (sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK)
+ arg.aggr_control = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ if (sta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
+ vif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+ }
+
+ ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
+ ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
+ if (ret)
+ goto exit;
+
+ /* Store the configured parameters in success case */
+ if (changed & IEEE80211_TID_CONF_NOACK) {
+ sta->noack[arg.tid] = arg.ack_policy;
+ arg.ack_policy = 0;
+ arg.aggr_control = 0;
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_RETRY) {
+ sta->retry_long[arg.tid] =
+ arg.retry_count;
+ arg.retry_count = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_AMPDU) {
+ sta->ampdu[arg.tid] = arg.aggr_control;
+ arg.aggr_control = 0;
+ }
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ sta->rate_ctrl[arg.tid] = arg.rate_ctrl;
+ arg.rate_ctrl = 0;
+ arg.rcode_flags = 0;
+ }
+ } else {
+ arvif->tid_conf_changed[arg.tid] |= changed;
+
+ if (changed & IEEE80211_TID_CONF_NOACK)
+ vif->noack[arg.tid] = arg.ack_policy;
+
+ if (changed & IEEE80211_TID_CONF_RETRY)
+ vif->retry_long[arg.tid] = arg.retry_count;
+
+ if (changed & IEEE80211_TID_CONF_AMPDU)
+ vif->ampdu[arg.tid] = arg.aggr_control;
+
+ if (changed & IEEE80211_TID_CONF_TX_BITRATE) {
+ vif->rate_ctrl[arg.tid] = arg.rate_ctrl;
+ vif->rate_code[arg.tid] = arg.rcode_flags;
+ }
+ }
+ }
+
+ if (sta)
+ goto exit;
+
+ ret = 0;
+ data.curr_vif = vif;
+ data.ar = ar;
+
+ ieee80211_iterate_stations_atomic(hw, ath10k_mac_vif_stations_tid_conf,
+ &data);
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_mac_op_tx,
.wake_tx_queue = ath10k_mac_op_wake_tx_queue,
@@ -8033,6 +8451,7 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw,
.switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx,
.sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove,
.sta_statistics = ath10k_sta_statistics,
+ .set_tid_config = ath10k_mac_op_set_tid_config,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
@@ -8695,6 +9114,29 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+ if (test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) {
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_NOACK_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_NOACK_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RETRY_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RETRY_CONFIG);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_AMPDU_CTRL);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_AMPDU_CTRL);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK);
+ ar->hw->wiphy->max_data_retry_count = ATH10K_MAX_RETRY_COUNT;
+ ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT;
+ } else {
+ ar->ops->set_tid_config = NULL;
+ ar->hw->wiphy->flags &= ~WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT;
+ }
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
--
1.9.1
^ permalink raw reply related
* [PATCHv2 9/9] ath10k: Add extended TID configuration support
From: Tamizh chelvam @ 2019-02-22 5:32 UTC (permalink / raw)
To: johannes, ath10k; +Cc: linux-wireless, Tamizh chelvam
In-Reply-To: <1550813554-11581-1-git-send-email-tamizhr@codeaurora.org>
This patch extend TID configuration support to configure
RTS_CTS control and TX rate limit. Tx rate limit is
similar to auto rate but it will be limited to the user
configured rate mask rather than the station's highest
supported rate mask. Here ext_tid_cfg_bitmap added
to notify the target which extended configuration
parameter has modified(here RTS_CTS).
WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT service flag
introduced to advertise this support.
Testing:
* Tested HW: QCA9984
* Tested FW: 10.4-3.9.0.2-00021
Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/core.c | 4 +++
drivers/net/wireless/ath/ath10k/mac.c | 48 ++++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.c | 7 ++---
drivers/net/wireless/ath/ath10k/wmi.h | 20 ++++++++++++++
4 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index ac2cf3f..248709d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2623,6 +2623,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
val |= WMI_10_4_REPORT_AIRTIME;
+ if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ ar->wmi.svc_map))
+ val |= WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT;
+
status = ath10k_mac_ext_resource_config(ar, val);
if (status) {
ath10k_err(ar,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5ba399f..eccda87 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2950,6 +2950,12 @@ static int ath10k_new_peer_tid_config(struct ath10k *ar,
arg.aggr_control = vif->ampdu[i];
arg.rate_ctrl = vif->rate_ctrl[i];
arg.rcode_flags = vif->rate_code[i];
+ if (vif->rtscts[i])
+ arg.ext_tid_cfg_bitmap =
+ WMI_EXT_TID_RTS_CTS_CONFIG;
+ else
+ arg.ext_tid_cfg_bitmap = 0;
+ arg.rtscts_ctrl = vif->rtscts[i];
}
if (vif->noack[i]) {
@@ -6559,6 +6565,10 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
if (txrate_type == NL80211_TX_RATE_FIXED)
*rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE;
+ else if (txrate_type == NL80211_TX_RATE_LIMITED &&
+ (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ ar->wmi.svc_map)))
+ *rate_ctrl = WMI_PEER_TID_CONFIG_RATE_UPPER_CAP;
else
return -EOPNOTSUPP;
return 0;
@@ -6625,6 +6635,14 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
arg->rate_ctrl = 0;
}
}
+
+ if (changed & IEEE80211_TID_CONF_RTSCTS) {
+ if (tid_conf->rtscts)
+ arg->rtscts_ctrl = tid_conf->rtscts - 1;
+ else
+ arg->rtscts_ctrl = WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE;
+ arg->ext_tid_cfg_bitmap = WMI_EXT_TID_RTS_CTS_CONFIG;
+ }
}
static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
@@ -6699,6 +6717,18 @@ static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
}
}
+ if (changed & IEEE80211_TID_CONF_RTSCTS) {
+ if (sta->rtscts[i]) {
+ arg.rtscts_ctrl = 0;
+ arg.ext_tid_cfg_bitmap = 0;
+ } else {
+ arg.rtscts_ctrl = vif->rtscts[i] - 1;
+ arg.ext_tid_cfg_bitmap =
+ WMI_EXT_TID_RTS_CTS_CONFIG;
+ config_apply = true;
+ }
+ }
+
arg.tid = i;
if (config_apply) {
@@ -8375,6 +8405,13 @@ static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
arg.rate_ctrl = 0;
arg.rcode_flags = 0;
}
+
+ if (changed & IEEE80211_TID_CONF_RTSCTS) {
+ sta->rtscts[arg.tid] =
+ tid_config->tid_conf[i].rtscts;
+ arg.rtscts_ctrl = 0;
+ arg.ext_tid_cfg_bitmap = 0;
+ }
} else {
arvif->tid_conf_changed[arg.tid] |= changed;
@@ -8391,6 +8428,10 @@ static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
vif->rate_ctrl[arg.tid] = arg.rate_ctrl;
vif->rate_code[arg.tid] = arg.rcode_flags;
}
+
+ if (changed & IEEE80211_TID_CONF_RTSCTS)
+ vif->rtscts[arg.tid] =
+ tid_config->tid_conf[i].rtscts;
}
}
@@ -9137,6 +9178,13 @@ int ath10k_mac_register(struct ath10k *ar)
ar->ops->set_tid_config = NULL;
ar->hw->wiphy->flags &= ~WIPHY_FLAG_HAS_MAX_DATA_RETRY_COUNT;
}
+
+ if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) {
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_RTSCTS_CTRL);
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_RTSCTS_CTRL);
+ }
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 44b66f2..583c398 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -8886,9 +8886,10 @@ static u32 ath10k_wmi_prepare_peer_qos(u8 uapsd_queues, u8 sp)
cmd->rcode_flags = cpu_to_le32(arg->rcode_flags);
ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d mac_addr %pM\n",
- arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control, arg->rate_ctrl,
- arg->rcode_flags, arg->retry_count, arg->peer_macaddr.addr);
+ "wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d rtscts %d ext_tid_cfg_bitmap %d mac_addr %pM\n",
+ arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control,
+ arg->rate_ctrl, arg->rcode_flags, arg->retry_count, arg->rtscts_ctrl,
+ arg->ext_tid_cfg_bitmap, arg->peer_macaddr.addr);
return skb;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 187c13e..21a328f 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -201,6 +201,7 @@ enum wmi_service {
WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
WMI_SERVICE_REPORT_AIRTIME,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
/* Remember to add the new value to wmi_service_name()! */
@@ -493,6 +494,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
SVCSTR(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT);
+ SVCSTR(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT);
case WMI_SERVICE_MAX:
return NULL;
@@ -822,6 +824,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_REPORT_AIRTIME, len);
SVCMAP(WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, len);
}
#undef SVCMAP
@@ -7169,6 +7173,16 @@ enum wmi_tid_rate_ctrl_conf {
WMI_TID_CONFIG_RATE_CONTROL_AUTO,
WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE,
WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE,
+ WMI_PEER_TID_CONFIG_RATE_UPPER_CAP,
+};
+
+enum wmi_tid_rtscts_control_conf {
+ WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE,
+ WMI_TID_CONFIG_RTSCTS_CONTROL_DISABLE,
+};
+
+enum wmi_ext_tid_config_map {
+ WMI_EXT_TID_RTS_CTS_CONFIG = BIT(0),
};
struct wmi_per_peer_per_tid_cfg_arg {
@@ -7180,6 +7194,8 @@ struct wmi_per_peer_per_tid_cfg_arg {
u8 rate_ctrl;
u32 retry_count;
u32 rcode_flags;
+ u32 ext_tid_cfg_bitmap;
+ u32 rtscts_ctrl;
};
struct wmi_peer_per_tid_cfg_cmd {
@@ -7195,6 +7211,10 @@ struct wmi_peer_per_tid_cfg_cmd {
__le32 rate_control;
__le32 rcode_flags;
__le32 retry_count;
+ /* See enum wmi_ext_tid_config_map */
+ __le32 ext_tid_cfg_bitmap;
+ /* see enum wmi_tid_rtscts_control_conf */
+ __le32 rtscts_ctrl;
} __packed;
enum wmi_txbf_conf {
--
1.9.1
^ permalink raw reply related
* [PATCH v3 1/3] cfg80211: Add support to set tx power for a station associated
From: Balaji Pothunoori @ 2019-02-22 6:33 UTC (permalink / raw)
To: johannes, linux-wireless; +Cc: ath10k, Ashok Raj Nagarajan, Balaji Pothunoori
From: Ashok Raj Nagarajan <arnagara@codeaurora.org>
This patch adds support to set transmit power setting type and transmit
power level attributes to NL80211_CMD_SET_STATION in order to facilitate
adjusting the transmit power level of a station associated to the AP.
The added attributes allow selection of automatic and limited transmit
power level, with the level defined in dBm format.
Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
---
v2: add txpwr structure
replaced nla_get_u32 with nla_get_u8/s16
added NLA_POLICY_RANGE check
v3: updated kernel-doc for sta_txpwr
structure and rebased
include/net/cfg80211.h | 22 ++++++++++++++++++++++
include/uapi/linux/nl80211.h | 14 ++++++++++++++
net/wireless/nl80211.c | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f81677f..410867a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -973,6 +973,27 @@ enum station_parameters_apply_mask {
STATION_PARAM_APPLY_UAPSD = BIT(0),
STATION_PARAM_APPLY_CAPABILITY = BIT(1),
STATION_PARAM_APPLY_PLINK_STATE = BIT(2),
+ STATION_PARAM_APPLY_STA_TXPOWER = BIT(3),
+};
+
+/**
+ * struct sta_txpwr - station txpower configuration
+ *
+ * Used to configure txpower for station.
+ *
+ * @power: tx power (in dBm) to be used for sending data traffic. If tx power
+ * is not provided, the default per-interface tx power setting will be
+ * overriding. Driver should be picking up the lowest tx power, either tx
+ * power per-interface or per-station.
+ * @type: In particular if TPC %type is NL80211_TX_POWER_LIMITED then tx power
+ * will be less than or equal to specified from userspace, whereas if TPC
+ * %type is NL80211_TX_POWER_AUTOMATIC then it indicates default tx power.
+ * NL80211_TX_POWER_FIXED is not a valid configuration option for
+ * per peer TPC.
+ */
+struct sta_txpwr {
+ s16 power;
+ enum nl80211_tx_power_setting type;
};
/**
@@ -1047,6 +1068,7 @@ struct station_parameters {
const struct ieee80211_he_cap_elem *he_capa;
u8 he_capa_len;
u16 airtime_weight;
+ struct sta_txpwr txpwr;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index dd4f86e..83040c6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2308,6 +2308,15 @@ enum nl80211_commands {
* @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime
* scheduler.
*
+ * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for
+ * station associated with the AP. See &enum nl80211_tx_power_setting for
+ * possible values.
+ * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This
+ * allows to set Tx power for a station. If this attribute is not included,
+ * the default per-interface tx power setting will be overriding. Driver
+ * should be picking up the lowest tx power, either tx power per-interface
+ * or per-station.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2758,6 +2767,8 @@ enum nl80211_attrs {
NL80211_ATTR_PEER_MEASUREMENTS,
NL80211_ATTR_AIRTIME_WEIGHT,
+ NL80211_ATTR_STA_TX_POWER_SETTING,
+ NL80211_ATTR_STA_TX_POWER,
/* add attributes here, update the policy in nl80211.c */
@@ -5343,6 +5354,8 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching
* (set/del PMKSA operations) in AP mode.
*
+ * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power
+ 8 to a station.
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5384,6 +5397,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+ NL80211_EXT_FEATURE_STA_TX_PWR,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 80878b4..f7bf282 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -331,6 +331,11 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
.len = NL80211_MAX_SUPP_RATES },
[NL80211_ATTR_STA_PLINK_ACTION] =
NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
+ [NL80211_ATTR_STA_TX_POWER_SETTING] =
+ NLA_POLICY_RANGE(NLA_U8,
+ NL80211_TX_POWER_AUTOMATIC,
+ NL80211_TX_POWER_FIXED),
+ [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
[NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
@@ -5387,6 +5392,31 @@ static int nl80211_set_station_tdls(struct genl_info *info,
return nl80211_parse_sta_wme(info, params);
}
+static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
+ struct station_parameters *params)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ int idx;
+
+ if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
+ if (!rdev->ops->set_tx_power ||
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_STA_TX_PWR))
+ return -EOPNOTSUPP;
+
+ idx = NL80211_ATTR_STA_TX_POWER_SETTING;
+ params->txpwr.type = nla_get_u8(info->attrs[idx]);
+
+ if (params->txpwr.type == NL80211_TX_POWER_LIMITED) {
+ idx = NL80211_ATTR_STA_TX_POWER;
+ params->txpwr.power = nla_get_s16(info->attrs[idx]);
+ }
+ params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER;
+ }
+
+ return 0;
+}
+
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5480,6 +5510,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
return -EOPNOTSUPP;
+ err = nl80211_parse_sta_txpower_setting(info, ¶ms);
+ if (err)
+ return err;
+
/* Include parameters for TDLS peer (will check later) */
err = nl80211_set_station_tdls(info, ¶ms);
if (err)
@@ -5617,6 +5651,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
return -EOPNOTSUPP;
+ err = nl80211_parse_sta_txpower_setting(info, ¶ms);
+ if (err)
+ return err;
+
err = nl80211_parse_sta_channel_info(info, ¶ms);
if (err)
return err;
--
2.7.4
^ permalink raw reply related
* [PATCH v3 2/3] mac80211: store tx power value from user to station
From: Balaji Pothunoori @ 2019-02-22 6:34 UTC (permalink / raw)
To: johannes, linux-wireless; +Cc: ath10k, Ashok Raj Nagarajan, Balaji Pothunoori
From: Ashok Raj Nagarajan <arnagara@codeaurora.org>
This patch introduce a new driver callback drv_sta_set_txpwr. This API will
copy the transmit power value passed from user space and call the driver
callback to set the tx power for the station.
Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
---
v2: add txpwr structure
added tx power set type in trace event
v3: updated kernel-doc for ieee80211_sta_txpwr
structure and rebased
include/net/mac80211.h | 22 ++++++++++++++++++++++
net/mac80211/cfg.c | 9 +++++++++
net/mac80211/driver-ops.c | 21 +++++++++++++++++++++
net/mac80211/driver-ops.h | 5 +++++
net/mac80211/trace.h | 30 ++++++++++++++++++++++++++++++
5 files changed, 87 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 97aed7b..74aad69 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1884,6 +1884,24 @@ struct ieee80211_sta_rates {
};
/**
+ * struct ieee80211_sta_txpwr - station txpower configuration
+ *
+ * Used to configure txpower for station.
+ *
+ * @power: indicates the tx power, in dBm, to be used when sending data frames
+ * to the STA.
+ * @type: In particular if TPC %type is NL80211_TX_POWER_LIMITED then tx power
+ * will be less than or equal to specified from userspace, whereas if TPC
+ * %type is NL80211_TX_POWER_AUTOMATIC then it indicates default tx power.
+ * NL80211_TX_POWER_FIXED is not a valid configuration option for
+ * per peer TPC.
+ */
+struct ieee80211_sta_txpwr {
+ s16 power;
+ enum nl80211_tx_power_setting type;
+};
+
+/**
* struct ieee80211_sta - station table entry
*
* A station table entry represents a station we are possibly
@@ -1969,6 +1987,7 @@ struct ieee80211_sta {
bool support_p2p_ps;
u16 max_rc_amsdu_len;
u16 max_tid_amsdu_len[IEEE80211_NUM_TIDS];
+ struct ieee80211_sta_txpwr txpwr;
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];
@@ -3785,6 +3804,9 @@ struct ieee80211_ops {
#endif
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
+ int (*sta_set_txpwr)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d65aa01..6a8b4a4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1417,6 +1417,15 @@ static int sta_apply_parameters(struct ieee80211_local *local,
if (params->listen_interval >= 0)
sta->listen_interval = params->listen_interval;
+ if (params->sta_modify_mask & STATION_PARAM_APPLY_STA_TXPOWER) {
+ sta->sta.txpwr.type = params->txpwr.type;
+ if (params->txpwr.type == NL80211_TX_POWER_LIMITED)
+ sta->sta.txpwr.power = params->txpwr.power;
+ ret = drv_sta_set_txpwr(local, sdata, sta);
+ if (ret)
+ return ret;
+ }
+
if (params->supported_rates) {
ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
sband, params->supported_rates,
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index bb886e7..839c002 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -138,6 +138,27 @@ int drv_sta_state(struct ieee80211_local *local,
return ret;
}
+__must_check
+int drv_sta_set_txpwr(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta)
+{
+ int ret = -EOPNOTSUPP;
+
+ might_sleep();
+
+ sdata = get_bss_sdata(sdata);
+ if (!check_sdata_in_driver(sdata))
+ return -EIO;
+
+ trace_drv_sta_set_txpwr(local, sdata, &sta->sta);
+ if (local->ops->sta_set_txpwr)
+ ret = local->ops->sta_set_txpwr(&local->hw, &sdata->vif,
+ &sta->sta);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
+
void drv_sta_rc_update(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta, u32 changed)
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index ba3c07b..2cc5bb2 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -529,6 +529,11 @@ int drv_sta_state(struct ieee80211_local *local,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state);
+__must_check
+int drv_sta_set_txpwr(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta);
+
void drv_sta_rc_update(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta, u32 changed);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 35ea0dc..c86e42a 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -828,6 +828,36 @@ TRACE_EVENT(drv_sta_state,
)
);
+TRACE_EVENT(drv_sta_set_txpwr,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta),
+
+ TP_ARGS(local, sdata, sta),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ STA_ENTRY
+ __field(s16, txpwr)
+ __field(u8, type)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ STA_ASSIGN;
+ __entry->txpwr = sta->txpwr.power;
+ __entry->type = sta->txpwr.type;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " txpwr: %d type %d",
+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG,
+ __entry->txpwr, __entry->type
+ )
+);
+
TRACE_EVENT(drv_sta_rc_update,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
--
2.7.4
^ permalink raw reply related
* [PATCH v3 3/3] ath10k: add support for controlling tx power to a station
From: Balaji Pothunoori @ 2019-02-22 6:35 UTC (permalink / raw)
To: ath10k, linux-wireless; +Cc: Ashok Raj Nagarajan, Balaji Pothunoori
From: Ashok Raj Nagarajan <arnagara@codeaurora.org>
This patch will add the support to control the transmit power for traffic
to a station associated with the AP.
Underlying firmware will enforce that the maximum tx power will be based
on the regulatory requirements. If the user given transmit power is greater
than the allowed tx power in the given channel, then the firmware will use
the maximum tx power in the same channel.
When 0 is sent to the firmware as tx power, it will revert to the default
tx power for the station.
Tested Hardware : QCA9984
Tested Firmware : 10.4-3.9.0.1-00013
Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
---
v2: removed mBm to dBm conversion
v3: rebased wmi.h changes
drivers/net/wireless/ath/ath10k/debug.h | 3 +++
drivers/net/wireless/ath/ath10k/mac.c | 39 +++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.h | 6 +++++
3 files changed, 48 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index db78e85..2e43d8d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -71,6 +71,9 @@ struct ath10k_pktlog_hdr {
/* FIXME: How to calculate the buffer size sanely? */
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
+#define ATH10K_TX_POWER_MAX_VAL 70
+#define ATH10K_TX_POWER_MIN_VAL 0
+
extern unsigned int ath10k_debug_mask;
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b73c23d..d6ed452 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6350,6 +6350,41 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif,
ar->num_stations--;
}
+static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct ath10k *ar = hw->priv;
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
+ int ret = 0;
+ s16 txpwr;
+
+ if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
+ txpwr = 0;
+ } else {
+ txpwr = sta->txpwr.power;
+ if (!txpwr)
+ return -EINVAL;
+ }
+
+ if (txpwr > ATH10K_TX_POWER_MAX_VAL || txpwr < ATH10K_TX_POWER_MIN_VAL)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
+ WMI_PEER_USE_FIXED_PWR, txpwr);
+ if (ret) {
+ ath10k_warn(ar, "failed to set tx power for station ret: %d\n",
+ ret);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
static int ath10k_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -8007,6 +8042,7 @@ static const struct ieee80211_ops ath10k_ops = {
.set_key = ath10k_set_key,
.set_default_unicast_key = ath10k_set_default_unicast_key,
.sta_state = ath10k_sta_state,
+ .sta_set_txpwr = ath10k_sta_set_txpwr,
.conf_tx = ath10k_conf_tx,
.remain_on_channel = ath10k_remain_on_channel,
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
@@ -8695,6 +8731,9 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+ if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map))
+ wiphy_ext_feature_set(ar->hw->wiphy,
+ NL80211_EXT_FEATURE_STA_TX_PWR);
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index d9b646f..1557253 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -200,6 +200,7 @@ enum wmi_service {
WMI_SERVICE_RTT_RESPONDER_ROLE,
WMI_SERVICE_PER_PACKET_SW_ENCRYPT,
WMI_SERVICE_REPORT_AIRTIME,
+ WMI_SERVICE_TX_PWR_PER_PEER,
/* Remember to add the new value to wmi_service_name()! */
@@ -367,6 +368,7 @@ enum wmi_10_4_service {
WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
WMI_10_4_SERVICE_REPORT_AIRTIME,
+ WMI_10_4_SERVICE_TX_PWR_PER_PEER,
};
static inline char *wmi_service_name(enum wmi_service service_id)
@@ -491,6 +493,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE);
SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT);
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
+ SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
case WMI_SERVICE_MAX:
return NULL;
@@ -818,6 +821,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len);
SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME,
WMI_SERVICE_REPORT_AIRTIME, len);
+ SVCMAP(WMI_10_4_SERVICE_TX_PWR_PER_PEER,
+ WMI_SERVICE_TX_PWR_PER_PEER, len);
}
#undef SVCMAP
@@ -6253,6 +6258,7 @@ enum wmi_peer_param {
WMI_PEER_USE_4ADDR = 0x6,
WMI_PEER_DEBUG = 0xa,
WMI_PEER_PHYMODE = 0xd,
+ WMI_PEER_USE_FIXED_PWR = 0x8,
WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */
};
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox