linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* rtl8xxxu: Wi-Fi Alliance Certification on Realtek RTL8188CUS
@ 2021-05-10 13:50 Reto Schneider
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
  0 siblings, 1 reply; 11+ messages in thread
From: Reto Schneider @ 2021-05-10 13:50 UTC (permalink / raw)
  To: Jes Sorensen, linux-wireless
  Cc: 邱名碩 (Chris Chiu),
	yhchuang, pkshih, tehuang, Larry Finger, kuba, kvalo, davem,
	Reto Schneider

Hi Jes,
Hi all,

Chris (writing code, testing) and me (testing) are working [1] on 
re-newing the Wi-Fi Alliance certification of an IoT gateway (STA) which 
uses the Realtek RTL8188CUS chip, and is (now) running Linux 5.10+ with 
the rtl8xxxu driver, firmware version 88.2 [2]. The existing 
certification [3] has been done using the RealTek-provided 8192cu driver 
[4] and and Linux 3.19.

While the rtl8xxxu in upstream is *very* stable, it lacks some features 
which are needed for the certification. I tried to summarize this in the 
wiki [1].

The following has been implemented by Chris (on top of mainline):
  - STBC Receive
  - TX power configuration (using the iw command, not regdb)

Still missing:
  - WMM support
  - A-MSDU RX support
  - TX power by rate

WIP (See also Chris' mail from earlier today):
  - A-MPDU
  - Rate adaption
  - TX descriptors

The motivation for writing this mail is that we we are currently blocked 
by an issue which we can not resolve already for some months: The 
re-transmission percentage of the rtl8xxxu is too high (rtl8192cu is the 
same) - way higher than what 8192cu achieves. According to Wireshark, 
the retransmission rate is always between 15-65% for the rtl8xxxu, while 
the realtek-provided 8192cu stays below 5%, often averaging at less than 
1% in my setup.

Examples with an Linksys WRT3200ACM AP (RA/TA: 24:f5:a2:c0:4e:b1, DA/SA: 
00:60:6e:00:07:7d, SSID customer-testwifi) and the DUT 
(00:1d:43:c0:19:8a) running iperf3 (TCP, TX):

rtl8xxxu:
  - 65% retries, many addresses reported which do not actually exists
  - Code: [5]
  - Captures: [7]

891cu:
  - 0.9% retries, no ghost addresses captured
  - Code:  [6]
  - Captures: [8]

I'd be really grateful for any kind of ideas, pointers, help.

Kind regards,
Reto

[1] Wiki entry (slightly outdated): 
https://wireless.wiki.kernel.org/en/users/wi-fi-alliance-certification
[2] rtl8912cu firmware v88.2, part of linux-firmware 20201118: 
https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/commit/rtlwifi/rtl8192cufw_TMSC.bin?id=2ea86675db1349235e9af0a9d0372b72da4db259
[3] Existing certification: 
https://api.cert.wi-fi.org/api/certificate/download/public?variantId=14856
[4] https://github.com/husqvarnagroup/smart-garden-gateway-seluxit-8192cu
[5] Most recent rtl8xxxu development: 
https://github.com/husqvarnagroup/linux/commit/909f13c8fd45260a622d148882030624d492c54f
[6] 8192cu for Linux 5.10+: 
https://github.com/husqvarnagroup/realtek-8192cu_rtl8188cus
[7] pcap: 
https://files.reto-schneider.ch/diesunddas/rtl8xxxu/2021-05-10/rtl8xxxu-65%25-retries.pcapng.gz
     shell: 
https://files.reto-schneider.ch/diesunddas/rtl8xxxu/2021-05-10/rtl8xxxu-65%25-retries-shell.log
[8] pcap: 
https://files.reto-schneider.ch/diesunddas/rtl8xxxu/2021-05-10/8192cu-0.9%25-retries.pcapng.gz
     shell: 
https://files.reto-schneider.ch/diesunddas/rtl8xxxu/2021-05-10/8192cu-0.9%25-retries-shell.log

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification
  2021-05-10 13:50 rtl8xxxu: Wi-Fi Alliance Certification on Realtek RTL8188CUS Reto Schneider
@ 2021-05-14  2:04 ` Reto Schneider
  2021-05-14  2:04   ` [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER Reto Schneider
                     ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, linux-kernel, netdev

From: Reto Schneider <reto.schneider@husqvarnagroup.com>

This is our most recent, WIP code. It is plagued by the too-frequent
retransmission issue as described in the original mail.

Any kind of help is welcome.


Chris Chiu (7):
  rtl8xxxu: add code to handle
    BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER
  rtl8xxxu: add handle for mac80211 get_txpower
  rtl8xxxu: Enable RX STBC by default
  rtl8xxxu: feed antenna information for mac80211
  rtl8xxxu: fill up txrate info for all chips
  rtl8xxxu: Fix the reported rx signal strength
  rtl8xxxu: Fix ampdu_action to get block ack session work

 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |   7 +
 .../realtek/rtl8xxxu/rtl8xxxu_8192c.c         |   2 +
 .../realtek/rtl8xxxu/rtl8xxxu_8723a.c         |   1 +
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 301 +++++++++++++++---
 4 files changed, 270 insertions(+), 41 deletions(-)

-- 
2.29.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  2021-05-14  4:09     ` Joe Perches
  2021-05-14  2:04   ` [PATCH 2/7] rtl8xxxu: add handle for mac80211 get_txpower Reto Schneider
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

The 'iw set txpower' is not handled by the driver. Use the existing
set_tx_power function to apply the tx power change

Signed-off-by: Chris Chiu <chiu@endlessos.org>
(cherry picked from commit 48f8fbccb7dff2d3c5f72a4267313d3c4cfc7df9)
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  3 +
 .../realtek/rtl8xxxu/rtl8xxxu_8192c.c         |  1 +
 .../realtek/rtl8xxxu/rtl8xxxu_8723a.c         |  1 +
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 90 +++++++++++++++++++
 4 files changed, 95 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index d6d1be4169e5..c15e4a52b9e5 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1426,6 +1426,7 @@ struct rtl8xxxu_fileops {
 	void (*enable_rf) (struct rtl8xxxu_priv *priv);
 	void (*disable_rf) (struct rtl8xxxu_priv *priv);
 	void (*usb_quirks) (struct rtl8xxxu_priv *priv);
+	u8 (*dbm_to_txpwridx)(struct rtl8xxxu_priv *priv, u16 mode, int dbm);
 	void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
 			      bool ht40);
 	void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
@@ -1508,6 +1509,8 @@ void rtl8xxxu_disabled_to_emu(struct rtl8xxxu_priv *priv);
 int rtl8xxxu_init_llt_table(struct rtl8xxxu_priv *priv);
 void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv);
 void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv);
+u8 rtl8xxxu_gen1_dbm_to_txpwridx(struct rtl8xxxu_priv *priv,
+				 u16 mode, int dbm);
 void rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv,
 				int channel, bool ht40);
 void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
index 27c4cb688be4..bb6df8cac82f 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
@@ -556,6 +556,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
 	.enable_rf = rtl8xxxu_gen1_enable_rf,
 	.disable_rf = rtl8xxxu_gen1_disable_rf,
 	.usb_quirks = rtl8xxxu_gen1_usb_quirks,
+	.dbm_to_txpwridx = rtl8xxxu_gen1_dbm_to_txpwridx,
 	.set_tx_power = rtl8xxxu_gen1_set_tx_power,
 	.update_rate_mask = rtl8xxxu_update_rate_mask,
 	.report_connect = rtl8xxxu_gen1_report_connect,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
index 4f93f88716a9..a5d56f61c4eb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
@@ -373,6 +373,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
 	.enable_rf = rtl8xxxu_gen1_enable_rf,
 	.disable_rf = rtl8xxxu_gen1_disable_rf,
 	.usb_quirks = rtl8xxxu_gen1_usb_quirks,
+	.dbm_to_txpwridx = rtl8xxxu_gen1_dbm_to_txpwridx,
 	.set_tx_power = rtl8xxxu_gen1_set_tx_power,
 	.update_rate_mask = rtl8xxxu_update_rate_mask,
 	.report_connect = rtl8xxxu_gen1_report_connect,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 5cd7ef3625c5..e8459cb6035f 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -1382,6 +1382,38 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw)
 	}
 }
 
+#define MAX_TXPWR_IDX_NMODE_92S		63
+
+u8
+rtl8xxxu_gen1_dbm_to_txpwridx(struct rtl8xxxu_priv *priv, u16 mode, int dbm)
+{
+	u8 txpwridx;
+	long offset;
+
+	switch (mode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+
+	if ((dbm - offset) > 0)
+		txpwridx = (u8)((dbm - offset) * 2);
+	else
+		txpwridx = 0;
+
+	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
+		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
+
+	return txpwridx;
+}
+
 void
 rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
 {
@@ -4508,6 +4540,55 @@ rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta)
 	return network_type;
 }
 
+static void rtl8xxxu_update_txpower(struct rtl8xxxu_priv *priv, int power)
+{
+	bool ht40 = false;
+	struct ieee80211_hw *hw = priv->hw;
+	int channel = hw->conf.chandef.chan->hw_value;
+	u8 cck_txpwridx, ofdm_txpwridx;
+	int i, group;
+
+	if (!priv->fops->dbm_to_txpwridx)
+		return;
+
+	switch (hw->conf.chandef.width) {
+	case NL80211_CHAN_WIDTH_20_NOHT:
+	case NL80211_CHAN_WIDTH_20:
+		ht40 = false;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		ht40 = true;
+		break;
+	default:
+		return;
+	}
+
+	// change the power level to power index
+	cck_txpwridx = priv->fops->dbm_to_txpwridx(priv, WIRELESS_MODE_B,
+						   power);
+	ofdm_txpwridx = priv->fops->dbm_to_txpwridx(priv, WIRELESS_MODE_N_24G,
+						    power);
+
+	if (ofdm_txpwridx - priv->ofdm_tx_power_index_diff[1].a > 0)
+		ofdm_txpwridx -= priv->ofdm_tx_power_index_diff[1].a;
+	else
+		ofdm_txpwridx = 0;
+
+	group = rtl8xxxu_gen1_channel_to_group(channel);
+
+	if (cck_txpwridx <= priv->cck_tx_power_index_A[group]) {
+		priv->cck_tx_power_index_A[group] = cck_txpwridx;
+		priv->cck_tx_power_index_B[group] = cck_txpwridx;
+	}
+
+	if (ofdm_txpwridx <= priv->ht40_1s_tx_power_index_A[group]) {
+		priv->ht40_1s_tx_power_index_A[i] = ofdm_txpwridx;
+		priv->ht40_1s_tx_power_index_B[i] = ofdm_txpwridx;
+	}
+
+	priv->fops->set_tx_power(priv, channel, ht40);
+}
+
 static void
 rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *bss_conf, u32 changed)
@@ -4604,6 +4685,12 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		dev_dbg(dev, "Changed BASIC_RATES!\n");
 		rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates);
 	}
+
+	if (changed & BSS_CHANGED_TXPOWER) {
+		dev_dbg(dev, "Changed TX power!\n");
+		//rtl8xxxu_update_txpower(priv, bss_conf->txpower);	// iterate
+		rtl8xxxu_update_txpower(priv, hw->conf.power_level);
+	}
 error:
 	return;
 }
@@ -5891,6 +5978,9 @@ static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed)
 		priv->fops->config_channel(hw);
 	}
 
+	if (changed & IEEE80211_CONF_CHANGE_POWER)
+		rtl8xxxu_update_txpower(priv, hw->conf.power_level);
+
 exit:
 	return ret;
 }
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/7] rtl8xxxu: add handle for mac80211 get_txpower
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
  2021-05-14  2:04   ` [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  2021-05-14  4:22     ` Joe Perches
  2021-05-14  2:04   ` [PATCH 3/7] rtl8xxxu: Enable RX STBC by default Reto Schneider
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

add .get_txpower handle for mac80211 operations for `iw` and `wext`
tools to get the underlying tx power (max limit).

Signed-off-by: Chris Chiu <chiu@endlessos.org>
(cherry picked from commit 2295263455630bd53eb51379e6e745b943d5017d)
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  3 +
 .../realtek/rtl8xxxu/rtl8xxxu_8192c.c         |  1 +
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 72 ++++++++++++++++++-
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index c15e4a52b9e5..3d16d6c9ff39 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1319,6 +1319,7 @@ struct rtl8xxxu_priv {
 	struct rtl8723au_idx ht20_tx_power_diff[RTL8723B_TX_COUNT];
 	struct rtl8723au_idx ht40_tx_power_diff[RTL8723B_TX_COUNT];
 	struct rtl8xxxu_power_base *power_base;
+	u8 cur_cck_txpwridx, cur_ofdm24g_txpwridx;
 	u32 chip_cut:4;
 	u32 rom_rev:4;
 	u32 is_multi_func:1;
@@ -1427,6 +1428,7 @@ struct rtl8xxxu_fileops {
 	void (*disable_rf) (struct rtl8xxxu_priv *priv);
 	void (*usb_quirks) (struct rtl8xxxu_priv *priv);
 	u8 (*dbm_to_txpwridx)(struct rtl8xxxu_priv *priv, u16 mode, int dbm);
+	int (*get_tx_power)(struct rtl8xxxu_priv *priv);
 	void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
 			      bool ht40);
 	void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
@@ -1513,6 +1515,7 @@ u8 rtl8xxxu_gen1_dbm_to_txpwridx(struct rtl8xxxu_priv *priv,
 				 u16 mode, int dbm);
 void rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv,
 				int channel, bool ht40);
+int rtl8xxxu_gen1_get_tx_power(struct rtl8xxxu_priv *priv);
 void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw);
 void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw);
 void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv);
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
index bb6df8cac82f..54f41af1015e 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
@@ -558,6 +558,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
 	.usb_quirks = rtl8xxxu_gen1_usb_quirks,
 	.dbm_to_txpwridx = rtl8xxxu_gen1_dbm_to_txpwridx,
 	.set_tx_power = rtl8xxxu_gen1_set_tx_power,
+	.get_tx_power = rtl8xxxu_gen1_get_tx_power,
 	.update_rate_mask = rtl8xxxu_update_rate_mask,
 	.report_connect = rtl8xxxu_gen1_report_connect,
 	.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index e8459cb6035f..585018383712 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -1414,6 +1414,55 @@ rtl8xxxu_gen1_dbm_to_txpwridx(struct rtl8xxxu_priv *priv, u16 mode, int dbm)
 	return txpwridx;
 }
 
+static int
+rtl8xxxu_gen1_txpwridx_to_dbm(struct rtl8xxxu_priv *priv, u16 mode, u8 idx)
+{
+	int offset;
+	int pwrout_dbm;
+
+	switch (mode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+	pwrout_dbm = idx / 2 + offset;
+
+	return pwrout_dbm;
+}
+
+int
+rtl8xxxu_gen1_get_tx_power(struct rtl8xxxu_priv *priv)
+{
+	u8 txpwr_level;
+	int txpwr_dbm;
+
+	txpwr_level = priv->cur_cck_txpwridx;
+	txpwr_dbm = rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_B,
+						  txpwr_level);
+	txpwr_level = priv->cur_ofdm24g_txpwridx +
+		      priv->ofdm_tx_power_index_diff[1].a;
+
+	if (rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_G, txpwr_level)
+	    > txpwr_dbm)
+		txpwr_dbm = rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_G,
+							  txpwr_level);
+	txpwr_level = priv->cur_ofdm24g_txpwridx;
+	if (rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_N_24G,
+					  txpwr_level) > txpwr_dbm)
+		txpwr_dbm = rtl8xxxu_gen1_txpwridx_to_dbm(priv,
+							  WIRELESS_MODE_N_24G,
+							  txpwr_level);
+
+	return txpwr_dbm;
+}
+
 void
 rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
 {
@@ -4540,6 +4589,19 @@ rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta)
 	return network_type;
 }
 
+static int rtl8xxxu_get_txpower(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif, int *dbm)
+{
+	struct rtl8xxxu_priv *priv = hw->priv;
+
+	if (!priv->fops->get_tx_power)
+		return -EOPNOTSUPP;
+
+	*dbm = priv->fops->get_tx_power(priv);
+
+	return 0;
+}
+
 static void rtl8xxxu_update_txpower(struct rtl8xxxu_priv *priv, int power)
 {
 	bool ht40 = false;
@@ -4569,10 +4631,12 @@ static void rtl8xxxu_update_txpower(struct rtl8xxxu_priv *priv, int power)
 	ofdm_txpwridx = priv->fops->dbm_to_txpwridx(priv, WIRELESS_MODE_N_24G,
 						    power);
 
-	if (ofdm_txpwridx - priv->ofdm_tx_power_index_diff[1].a > 0)
+	if (ofdm_txpwridx - priv->ofdm_tx_power_index_diff[1].a > 0) {
+		/* refer to rtlefuse->legacy_ht_txpowerdiff in vendor driver */
 		ofdm_txpwridx -= priv->ofdm_tx_power_index_diff[1].a;
-	else
+	} else {
 		ofdm_txpwridx = 0;
+	}
 
 	group = rtl8xxxu_gen1_channel_to_group(channel);
 
@@ -4586,6 +4650,9 @@ static void rtl8xxxu_update_txpower(struct rtl8xxxu_priv *priv, int power)
 		priv->ht40_1s_tx_power_index_B[i] = ofdm_txpwridx;
 	}
 
+	priv->cur_cck_txpwridx = priv->cck_tx_power_index_A[group];
+	priv->cur_ofdm24g_txpwridx = priv->ht40_1s_tx_power_index_A[group];
+
 	priv->fops->set_tx_power(priv, channel, ht40);
 }
 
@@ -6542,6 +6609,7 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
 	.set_key = rtl8xxxu_set_key,
 	.ampdu_action = rtl8xxxu_ampdu_action,
 	.sta_statistics = rtl8xxxu_sta_statistics,
+	.get_txpower = rtl8xxxu_get_txpower,
 };
 
 static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv,
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/7] rtl8xxxu: Enable RX STBC by default
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
  2021-05-14  2:04   ` [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER Reto Schneider
  2021-05-14  2:04   ` [PATCH 2/7] rtl8xxxu: add handle for mac80211 get_txpower Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  2021-05-14  2:04   ` [PATCH 4/7] rtl8xxxu: feed antenna information for mac80211 Reto Schneider
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

(cherry picked from commit f740aef70abe336c63b9a20c5603402dc90cdfee)
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 585018383712..d5c53d6dec33 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -6821,6 +6821,8 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
 		sband->ht_cap.mcs.rx_mask[1] = 0xff;
 		sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
 	}
+	/* only one spatial-stream STBC RX supported */
+	sband->ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
 	sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 	/*
 	 * Some APs will negotiate HT20_40 in a noisy environment leading
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/7] rtl8xxxu: feed antenna information for mac80211
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
                     ` (2 preceding siblings ...)
  2021-05-14  2:04   ` [PATCH 3/7] rtl8xxxu: Enable RX STBC by default Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  2021-05-14  2:04   ` [PATCH 5/7] rtl8xxxu: fill up txrate info for all chips Reto Schneider
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

(cherry picked from commit 557e87b5db655394a16c9b54a07a2fc11f1ea618)
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index d5c53d6dec33..0a04ce00b1fe 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -1688,6 +1688,7 @@ static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv)
 static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv)
 {
 	struct device *dev = &priv->udev->dev;
+	struct ieee80211_hw *hw = priv->hw;
 	u32 val32, bonding;
 	u16 val16;
 
@@ -1764,6 +1765,8 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv)
 		priv->usb_interrupts = 1;
 		priv->has_wifi = 1;
 	}
+	hw->wiphy->available_antennas_tx = BIT(priv->tx_paths) - 1;
+	hw->wiphy->available_antennas_rx = BIT(priv->rx_paths) - 1;
 
 	switch (priv->rtl_chip) {
 	case RTL8188E:
@@ -4363,6 +4366,17 @@ static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv,
 	rtl8xxxu_debug = tmp_debug;
 }
 
+static
+int rtl8xxxu_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+	struct rtl8xxxu_priv *priv = hw->priv;
+
+	*tx_ant = BIT(priv->tx_paths) - 1;
+	*rx_ant = BIT(priv->rx_paths) - 1;
+
+	return 0;
+}
+
 static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif, const u8 *mac)
 {
@@ -6609,6 +6623,7 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
 	.set_key = rtl8xxxu_set_key,
 	.ampdu_action = rtl8xxxu_ampdu_action,
 	.sta_statistics = rtl8xxxu_sta_statistics,
+	.get_antenna = rtl8xxxu_get_antenna,
 	.get_txpower = rtl8xxxu_get_txpower,
 };
 
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/7] rtl8xxxu: fill up txrate info for all chips
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
                     ` (3 preceding siblings ...)
  2021-05-14  2:04   ` [PATCH 4/7] rtl8xxxu: feed antenna information for mac80211 Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  2021-05-14  2:04   ` [PATCH 6/7] rtl8xxxu: Fix the reported rx signal strength Reto Schneider
  2021-05-14  2:04   ` [PATCH 7/7] rtl8xxxu: Fix ampdu_action to get block ack session work Reto Schneider
  6 siblings, 0 replies; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

RTL8188CUS/RTL8192CU (gen1) doesn't support rate adaptive report
hence no real txrate info can be retrieved. The vendor driver reports
the highest rate in HT capabilities from AP side.
This commit follows the same way to avoid empty info for txrate.

(cherry picked from commit 831ecaf5e80b1cba26d3606b064020a22268f694)
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 86 ++++++++++++-------
 1 file changed, 57 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 0a04ce00b1fe..0c997c360028 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -4670,6 +4670,35 @@ static void rtl8xxxu_update_txpower(struct rtl8xxxu_priv *priv, int power)
 	priv->fops->set_tx_power(priv, channel, ht40);
 }
 
+static struct ieee80211_rate rtl8xxxu_legacy_ratetable[] = {
+	{.bitrate = 10, .hw_value = 0x00,},
+	{.bitrate = 20, .hw_value = 0x01,},
+	{.bitrate = 55, .hw_value = 0x02,},
+	{.bitrate = 110, .hw_value = 0x03,},
+	{.bitrate = 60, .hw_value = 0x04,},
+	{.bitrate = 90, .hw_value = 0x05,},
+	{.bitrate = 120, .hw_value = 0x06,},
+	{.bitrate = 180, .hw_value = 0x07,},
+	{.bitrate = 240, .hw_value = 0x08,},
+	{.bitrate = 360, .hw_value = 0x09,},
+	{.bitrate = 480, .hw_value = 0x0a,},
+	{.bitrate = 540, .hw_value = 0x0b,},
+};
+
+static void rtl8xxxu_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
+{
+	if (rate <= DESC_RATE_54M)
+		return;
+
+	if (rate >= DESC_RATE_MCS0 && rate <= DESC_RATE_MCS15) {
+		if (rate < DESC_RATE_MCS8)
+			*nss = 1;
+		else
+			*nss = 2;
+		*mcs = rate - DESC_RATE_MCS0;
+	}
+}
+
 static void
 rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *bss_conf, u32 changed)
@@ -4677,9 +4706,12 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
 	struct ieee80211_sta *sta;
+	struct rtl8xxxu_ra_report *rarpt;
 	u32 val32;
 	u8 val8;
 
+	rarpt = &priv->ra_report;
+
 	if (changed & BSS_CHANGED_ASSOC) {
 		dev_dbg(dev, "Changed ASSOC: %i!\n", bss_conf->assoc);
 
@@ -4688,6 +4720,9 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		if (bss_conf->assoc) {
 			u32 ramask;
 			int sgi = 0;
+			u8 highest_rate;
+			u8 mcs = 0, nss = 0;
+			u32 bit_rate;
 
 			rcu_read_lock();
 			sta = ieee80211_find_sta(vif, bss_conf->bssid);
@@ -4712,6 +4747,28 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 				sgi = 1;
 			rcu_read_unlock();
 
+			highest_rate = fls(ramask) - 1;
+			if (highest_rate < DESC_RATE_MCS0) {
+				rarpt->txrate.legacy =
+					rtl8xxxu_legacy_ratetable[highest_rate].bitrate;
+			} else {
+				rtl8xxxu_desc_to_mcsrate(highest_rate, &mcs, &nss);
+				rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS;
+
+				rarpt->txrate.mcs = mcs;
+				rarpt->txrate.nss = nss;
+
+				if (sgi) {
+					rarpt->txrate.flags |=
+						RATE_INFO_FLAGS_SHORT_GI;
+				}
+
+				rarpt->txrate.bw |= RATE_INFO_BW_20;
+			}
+			bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate);
+			rarpt->bit_rate = bit_rate;
+			rarpt->desc_rate = highest_rate;
+
 			priv->vif = vif;
 			priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
 
@@ -5557,35 +5614,6 @@ void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv)
 	}
 }
 
-static struct ieee80211_rate rtl8xxxu_legacy_ratetable[] = {
-	{.bitrate = 10, .hw_value = 0x00,},
-	{.bitrate = 20, .hw_value = 0x01,},
-	{.bitrate = 55, .hw_value = 0x02,},
-	{.bitrate = 110, .hw_value = 0x03,},
-	{.bitrate = 60, .hw_value = 0x04,},
-	{.bitrate = 90, .hw_value = 0x05,},
-	{.bitrate = 120, .hw_value = 0x06,},
-	{.bitrate = 180, .hw_value = 0x07,},
-	{.bitrate = 240, .hw_value = 0x08,},
-	{.bitrate = 360, .hw_value = 0x09,},
-	{.bitrate = 480, .hw_value = 0x0a,},
-	{.bitrate = 540, .hw_value = 0x0b,},
-};
-
-static void rtl8xxxu_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
-{
-	if (rate <= DESC_RATE_54M)
-		return;
-
-	if (rate >= DESC_RATE_MCS0 && rate <= DESC_RATE_MCS15) {
-		if (rate < DESC_RATE_MCS8)
-			*nss = 1;
-		else
-			*nss = 2;
-		*mcs = rate - DESC_RATE_MCS0;
-	}
-}
-
 static void rtl8xxxu_c2hcmd_callback(struct work_struct *work)
 {
 	struct rtl8xxxu_priv *priv;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/7] rtl8xxxu: Fix the reported rx signal strength
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
                     ` (4 preceding siblings ...)
  2021-05-14  2:04   ` [PATCH 5/7] rtl8xxxu: fill up txrate info for all chips Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  2021-05-14  2:04   ` [PATCH 7/7] rtl8xxxu: Fix ampdu_action to get block ack session work Reto Schneider
  6 siblings, 0 replies; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

In rtl8xxxx_rx_query_desc for each chip in rtlwifi family, the
rx_status->signal is always the status->recvsignalpower + 10.

We also observe the same thing in air capture that the RSSI is
always ~10dBm higher than reported from driver.

Add this 10dBm to avoid confusion.

(cherry picked from commit e1a4f83da577474dfa23e85483a83eb7fb707edc)
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 0c997c360028..088e007e8bd0 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -5319,6 +5319,11 @@ static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
 		rx_status->signal =
 			(phy_stats->cck_sig_qual_ofdm_pwdb_all >> 1) - 110;
 	}
+
+	// refers to rtlxxxx_rx_query_desc of rtlwifi/rtlxxxx/trx.c
+	// needs to verify on RTL8723BU
+	if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E)
+		rx_status->signal += 10;
 }
 
 static void rtl8xxxu_free_rx_resources(struct rtl8xxxu_priv *priv)
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/7] rtl8xxxu: Fix ampdu_action to get block ack session work
  2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
                     ` (5 preceding siblings ...)
  2021-05-14  2:04   ` [PATCH 6/7] rtl8xxxu: Fix the reported rx signal strength Reto Schneider
@ 2021-05-14  2:04   ` Reto Schneider
  6 siblings, 0 replies; 11+ messages in thread
From: Reto Schneider @ 2021-05-14  2:04 UTC (permalink / raw)
  To: Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

From: Chris Chiu <chiu@endlessos.org>

The HAS_RATE_CONTROL hw capability needs to be unset for the mac80211
rate control to work. The mac80211 rate control will be in charge
of the TX aggregation related work so the AMPDU TX part in each
driver should be modified accordingly.

Signed-off-by: Chris Chiu <chiu@endlessos.org>
(cherry picked from commit c470f7aed67f223d941e3da6e9d2a464dd0083ee)

Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
---

 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  1 +
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 35 ++++++++++++-------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 3d16d6c9ff39..65620ecf9ac2 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1384,6 +1384,7 @@ struct rtl8xxxu_priv {
 	u8 no_pape:1;
 	u8 int_buf[USB_INTR_CONTENT_LENGTH];
 	u8 rssi_level;
+	u8 agg_state_bitmap;
 	/*
 	 * Only one virtual interface permitted because only STA mode
 	 * is supported and no iface_combinations are provided.
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 088e007e8bd0..7ce27d1bb27a 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -5030,6 +5030,8 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
 	struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
+	u8 *qc = ieee80211_get_qos_ctl(hdr);
+	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
 	u32 rate;
 	u16 rate_flags = tx_info->control.rates[0].flags;
 	u16 seq_number;
@@ -5053,10 +5055,12 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
 
 	tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC32_SEQ_SHIFT);
 
-	if (ampdu_enable)
+	if (ampdu_enable && (priv->agg_state_bitmap & BIT(tid)) &&
+	    (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
 		tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_ENABLE);
-	else
+	} else {
 		tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_BREAK);
+	}
 
 	if (ieee80211_is_mgmt(hdr->frame_control)) {
 		tx_desc->txdw5 = cpu_to_le32(rate);
@@ -5101,6 +5105,8 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
 	struct rtl8xxxu_txdesc40 *tx_desc40;
+	u8 *qc = ieee80211_get_qos_ctl(hdr);
+	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
 	u32 rate;
 	u16 rate_flags = tx_info->control.rates[0].flags;
 	u16 seq_number;
@@ -5127,10 +5133,13 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
 
 	tx_desc40->txdw9 = cpu_to_le32((u32)seq_number << TXDESC40_SEQ_SHIFT);
 
-	if (ampdu_enable)
+	if (ampdu_enable && (priv->agg_state_bitmap & BIT(tid)) &&
+	    (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
 		tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_ENABLE);
-	else
+		tx_desc40->txdw3 |= cpu_to_le32(0x1f << 17);
+	} else {
 		tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_BREAK);
+	}
 
 	if (ieee80211_is_mgmt(hdr->frame_control)) {
 		tx_desc40->txdw4 = cpu_to_le32(rate);
@@ -6299,6 +6308,7 @@ rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct device *dev = &priv->udev->dev;
 	u8 ampdu_factor, ampdu_density;
 	struct ieee80211_sta *sta = params->sta;
+	u16 tid = params->tid;
 	enum ieee80211_ampdu_mlme_action action = params->action;
 
 	switch (action) {
@@ -6311,17 +6321,19 @@ rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		dev_dbg(dev,
 			"Changed HT: ampdu_factor %02x, ampdu_density %02x\n",
 			ampdu_factor, ampdu_density);
-		break;
+		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
+	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
-		dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH\n", __func__);
-		rtl8xxxu_set_ampdu_factor(priv, 0);
-		rtl8xxxu_set_ampdu_min_space(priv, 0);
-		break;
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-		dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH_CONT\n",
-			 __func__);
+		dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP\n", __func__);
 		rtl8xxxu_set_ampdu_factor(priv, 0);
 		rtl8xxxu_set_ampdu_min_space(priv, 0);
+		priv->agg_state_bitmap &= ~BIT(tid);
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_OPERATIONAL\n", __func__);
+		priv->agg_state_bitmap |= BIT(tid);
 		break;
 	case IEEE80211_AMPDU_RX_START:
 		dev_dbg(dev, "%s: IEEE80211_AMPDU_RX_START\n", __func__);
@@ -6893,7 +6905,6 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
 	/*
 	 * The firmware handles rate control
 	 */
-	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
 
 	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER
  2021-05-14  2:04   ` [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER Reto Schneider
@ 2021-05-14  4:09     ` Joe Perches
  0 siblings, 0 replies; 11+ messages in thread
From: Joe Perches @ 2021-05-14  4:09 UTC (permalink / raw)
  To: Reto Schneider, Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

On Fri, 2021-05-14 at 04:04 +0200, Reto Schneider wrote:
> From: Chris Chiu <chiu@endlessos.org>
> 
> The 'iw set txpower' is not handled by the driver. Use the existing
> set_tx_power function to apply the tx power change

trivial notes:

> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
[]
> @@ -1382,6 +1382,38 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw)
>  	}
>  }
>  
> 
> +#define MAX_TXPWR_IDX_NMODE_92S		63
> +
> +u8
> +rtl8xxxu_gen1_dbm_to_txpwridx(struct rtl8xxxu_priv *priv, u16 mode, int dbm)
> +{
> +	u8 txpwridx;
> +	long offset;

why should offset be long when dbm is int?

> +
> +	switch (mode) {
> +	case WIRELESS_MODE_B:
> +		offset = -7;
> +		break;
> +	case WIRELESS_MODE_G:
> +	case WIRELESS_MODE_N_24G:
> +		offset = -8;
> +		break;
> +	default:
> +		offset = -8;
> +		break;
> +	}
> +
> +	if ((dbm - offset) > 0)
> +		txpwridx = (u8)((dbm - offset) * 2);

overflow of u8 when dbm >= 136?


> +	else
> +		txpwridx = 0;
> +
> +	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
> +		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
> +
> +	return txpwridx;
> +}
> +
>  void
>  rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
>  {
> @@ -4508,6 +4540,55 @@ rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta)
>  	return network_type;
>  }
>  
> 
> +static void rtl8xxxu_update_txpower(struct rtl8xxxu_priv *priv, int power)
> +{
> +	bool ht40 = false;

unnecessary initializations.

> +	struct ieee80211_hw *hw = priv->hw;
> +	int channel = hw->conf.chandef.chan->hw_value;
> +	u8 cck_txpwridx, ofdm_txpwridx;
> +	int i, group;
> +
> +	if (!priv->fops->dbm_to_txpwridx)
> +		return;
> +
> +	switch (hw->conf.chandef.width) {
> +	case NL80211_CHAN_WIDTH_20_NOHT:
> +	case NL80211_CHAN_WIDTH_20:
> +		ht40 = false;
> +		break;
> +	case NL80211_CHAN_WIDTH_40:
> +		ht40 = true;
> +		break;
> +	default:
> +		return;
> +	}



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/7] rtl8xxxu: add handle for mac80211 get_txpower
  2021-05-14  2:04   ` [PATCH 2/7] rtl8xxxu: add handle for mac80211 get_txpower Reto Schneider
@ 2021-05-14  4:22     ` Joe Perches
  0 siblings, 0 replies; 11+ messages in thread
From: Joe Perches @ 2021-05-14  4:22 UTC (permalink / raw)
  To: Reto Schneider, Jes.Sorensen, linux-wireless, pkshih
  Cc: yhchuang, Larry.Finger, tehuang, reto.schneider, ccchiu77, kvalo,
	davem, kuba, Chris Chiu, linux-kernel, netdev

On Fri, 2021-05-14 at 04:04 +0200, Reto Schneider wrote:
> From: Chris Chiu <chiu@endlessos.org>
> 
> add .get_txpower handle for mac80211 operations for `iw` and `wext`
> tools to get the underlying tx power (max limit).
[]
> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
[]

> +int
> +rtl8xxxu_gen1_get_tx_power(struct rtl8xxxu_priv *priv)
> +{
> +	u8 txpwr_level;
> +	int txpwr_dbm;
> +
> +	txpwr_level = priv->cur_cck_txpwridx;
> +	txpwr_dbm = rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_B,
> +						  txpwr_level);
> +	txpwr_level = priv->cur_ofdm24g_txpwridx +
> +		      priv->ofdm_tx_power_index_diff[1].a;
> +
> +	if (rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_G, txpwr_level)
> +	    > txpwr_dbm)
> +		txpwr_dbm = rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_G,
> +							  txpwr_level);

probably better to use a temporaries instead of multiple calls.

	foo = rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_G, txpwr_level);
	if (foo > txpwr_dbm)
		txpwr_dbm = foo;

> +	txpwr_level = priv->cur_ofdm24g_txpwridx;
> +	if (rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_N_24G,
> +					  txpwr_level) > txpwr_dbm)
> +		txpwr_dbm = rtl8xxxu_gen1_txpwridx_to_dbm(priv,
> +							  WIRELESS_MODE_N_24G,
> +							  txpwr_level);
> +
> +	return txpwr_dbm;

	foo = rtl8xxxu_gen1_txpwridx_to_dbm(priv, WIRELESS_MODE_N_24G, txpwr_level);

	return min(txpwr_dbm, foo);



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-05-14  4:22 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-10 13:50 rtl8xxxu: Wi-Fi Alliance Certification on Realtek RTL8188CUS Reto Schneider
2021-05-14  2:04 ` [PATCH 0/7] [RFC] rtl8xxxu/RTL8188CUS: Wi-Fi Alliance Certification Reto Schneider
2021-05-14  2:04   ` [PATCH 1/7] rtl8xxxu: add code to handle BSS_CHANGED_TXPOWER/IEEE80211_CONF_CHANGE_POWER Reto Schneider
2021-05-14  4:09     ` Joe Perches
2021-05-14  2:04   ` [PATCH 2/7] rtl8xxxu: add handle for mac80211 get_txpower Reto Schneider
2021-05-14  4:22     ` Joe Perches
2021-05-14  2:04   ` [PATCH 3/7] rtl8xxxu: Enable RX STBC by default Reto Schneider
2021-05-14  2:04   ` [PATCH 4/7] rtl8xxxu: feed antenna information for mac80211 Reto Schneider
2021-05-14  2:04   ` [PATCH 5/7] rtl8xxxu: fill up txrate info for all chips Reto Schneider
2021-05-14  2:04   ` [PATCH 6/7] rtl8xxxu: Fix the reported rx signal strength Reto Schneider
2021-05-14  2:04   ` [PATCH 7/7] rtl8xxxu: Fix ampdu_action to get block ack session work Reto Schneider

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).