]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
wifi: rtl8xxxu: Fix the CCK RSSI calculation
authorBitterblue Smith <rtl8821cerfe2@gmail.com>
Tue, 1 Nov 2022 20:33:09 +0000 (22:33 +0200)
committerKalle Valo <kvalo@kernel.org>
Fri, 4 Nov 2022 11:01:34 +0000 (13:01 +0200)
The CCK RSSI calculation is incorrect for the RTL8723BU, RTL8192EU,
and RTL8188FU. Add new functions for these chips with code copied from
their vendor drivers. Use the old code only for the RTL8723AU and
RTL8192CU.

I didn't notice any difference in the reported signal strength with my
RTL8188FU, but I didn't look very hard either.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/926c838f-4997-698b-4da9-44582e2af99a@gmail.com
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h

index eee48817d4d73066e03185eddd48a38a633ab6d7..6ff554ba02507a9aeb44cac5bd28b9e92948e2a1 100644 (file)
@@ -1395,6 +1395,7 @@ struct rtl8xxxu_priv {
        u32 ep_tx_normal_queue:1;
        u32 ep_tx_low_queue:1;
        u32 rx_buf_aggregation:1;
+       u32 cck_agc_report_type:1;
        u8 default_crystal_cap;
        unsigned int pipe_interrupt;
        unsigned int pipe_in;
@@ -1499,6 +1500,7 @@ struct rtl8xxxu_fileops {
                             bool short_preamble, bool ampdu_enable,
                             u32 rts_rate);
        void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap);
+       s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
        int writeN_block_size;
        int rx_agg_buf_size;
        char tx_desc_size;
@@ -1609,6 +1611,7 @@ void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
                           u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
 void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
 void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
+s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
 
 extern struct rtl8xxxu_fileops rtl8188fu_fops;
 extern struct rtl8xxxu_fileops rtl8192cu_fops;
index 9f40d261ac718d58c86540934b40222a1d85dfbe..5a5b7fa4283c4fe710423c2725f8b2dcfa05b8d7 100644 (file)
@@ -1658,6 +1658,37 @@ static void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
        cfo->crystal_cap = crystal_cap;
 }
 
+static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+       s8 rx_pwr_all = 0x00;
+       u8 vga_idx, lna_idx;
+
+       lna_idx = (cck_agc_rpt & 0xE0) >> 5;
+       vga_idx = cck_agc_rpt & 0x1F;
+
+       switch (lna_idx) {
+       case 7:
+               if (vga_idx <= 27)
+                       rx_pwr_all = -100 + 2 * (27 - vga_idx);
+               else
+                       rx_pwr_all = -100;
+               break;
+       case 5:
+               rx_pwr_all = -74 + 2 * (21 - vga_idx);
+               break;
+       case 3:
+               rx_pwr_all = -60 + 2 * (20 - vga_idx);
+               break;
+       case 1:
+               rx_pwr_all = -44 + 2 * (19 - vga_idx);
+               break;
+       default:
+               break;
+       }
+
+       return rx_pwr_all;
+}
+
 struct rtl8xxxu_fileops rtl8188fu_fops = {
        .parse_efuse = rtl8188fu_parse_efuse,
        .load_firmware = rtl8188fu_load_firmware,
@@ -1682,6 +1713,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
        .report_connect = rtl8xxxu_gen2_report_connect,
        .fill_txdesc = rtl8xxxu_fill_txdesc_v2,
        .set_crystal_cap = rtl8188f_set_crystal_cap,
+       .cck_rssi = rtl8188f_cck_rssi,
        .writeN_block_size = 128,
        .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
        .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
index e9bc94edfa79a1c24a22d0f69831f98c3a82d1b6..9dfeeaa74927b399b2eaee63f73a3b8490280b59 100644 (file)
@@ -561,6 +561,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
        .update_rate_mask = rtl8xxxu_update_rate_mask,
        .report_connect = rtl8xxxu_gen1_report_connect,
        .fill_txdesc = rtl8xxxu_fill_txdesc_v1,
+       .cck_rssi = rtl8723a_cck_rssi,
        .writeN_block_size = 128,
        .rx_agg_buf_size = 16000,
        .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
index bc0ec72d0126f9087ef680c9a6db637ff3dc1fd1..973a02afc82bd40ca339aa98b46618d8d10669b6 100644 (file)
@@ -1670,6 +1670,28 @@ static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
        rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8);
 }
 
+static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+       static const s8 lna_gain_table_0[8] = {15, 9, -10, -21, -23, -27, -43, -44};
+       static const s8 lna_gain_table_1[8] = {24, 18, 13, -4, -11, -18, -31, -36};
+
+       s8 rx_pwr_all = 0x00;
+       u8 vga_idx, lna_idx;
+       s8 lna_gain = 0;
+
+       lna_idx = (cck_agc_rpt & 0xE0) >> 5;
+       vga_idx = cck_agc_rpt & 0x1F;
+
+       if (priv->cck_agc_report_type == 0)
+               lna_gain = lna_gain_table_0[lna_idx];
+       else
+               lna_gain = lna_gain_table_1[lna_idx];
+
+       rx_pwr_all = lna_gain - (2 * vga_idx);
+
+       return rx_pwr_all;
+}
+
 struct rtl8xxxu_fileops rtl8192eu_fops = {
        .parse_efuse = rtl8192eu_parse_efuse,
        .load_firmware = rtl8192eu_load_firmware,
@@ -1691,6 +1713,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = {
        .report_connect = rtl8xxxu_gen2_report_connect,
        .fill_txdesc = rtl8xxxu_fill_txdesc_v2,
        .set_crystal_cap = rtl8723a_set_crystal_cap,
+       .cck_rssi = rtl8192e_cck_rssi,
        .writeN_block_size = 128,
        .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
        .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
index 552763a2215c1d3875be983d9b14968ec4314993..8d8eb16a097037bfcdf626a3b518d05954af2b3f 100644 (file)
@@ -386,6 +386,28 @@ void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
        cfo->crystal_cap = crystal_cap;
 }
 
+s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+       s8 rx_pwr_all = 0x00;
+
+       switch (cck_agc_rpt & 0xc0) {
+       case 0xc0:
+               rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+               break;
+       case 0x80:
+               rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+               break;
+       case 0x40:
+               rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+               break;
+       case 0x00:
+               rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+               break;
+       }
+
+       return rx_pwr_all;
+}
+
 struct rtl8xxxu_fileops rtl8723au_fops = {
        .parse_efuse = rtl8723au_parse_efuse,
        .load_firmware = rtl8723au_load_firmware,
@@ -408,6 +430,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
        .report_connect = rtl8xxxu_gen1_report_connect,
        .fill_txdesc = rtl8xxxu_fill_txdesc_v1,
        .set_crystal_cap = rtl8723a_set_crystal_cap,
+       .cck_rssi = rtl8723a_cck_rssi,
        .writeN_block_size = 1024,
        .rx_agg_buf_size = 16000,
        .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
index 9bfcb1e121832c6f5e24bd080a112954dae1ebe2..9214c1d3b64457e3753914643e697fcf51d1fd92 100644 (file)
@@ -1639,6 +1639,34 @@ static void rtl8723bu_init_statistics(struct rtl8xxxu_priv *priv)
        rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32);
 }
 
+static s8 rtl8723b_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+       s8 rx_pwr_all = 0x00;
+       u8 vga_idx, lna_idx;
+
+       lna_idx = (cck_agc_rpt & 0xE0) >> 5;
+       vga_idx = cck_agc_rpt & 0x1F;
+
+       switch (lna_idx) {
+       case 6:
+               rx_pwr_all = -34 - (2 * vga_idx);
+               break;
+       case 4:
+               rx_pwr_all = -14 - (2 * vga_idx);
+               break;
+       case 1:
+               rx_pwr_all = 6 - (2 * vga_idx);
+               break;
+       case 0:
+               rx_pwr_all = 16 - (2 * vga_idx);
+               break;
+       default:
+               break;
+       }
+
+       return rx_pwr_all;
+}
+
 struct rtl8xxxu_fileops rtl8723bu_fops = {
        .parse_efuse = rtl8723bu_parse_efuse,
        .load_firmware = rtl8723bu_load_firmware,
@@ -1663,6 +1691,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
        .report_connect = rtl8xxxu_gen2_report_connect,
        .fill_txdesc = rtl8xxxu_fill_txdesc_v2,
        .set_crystal_cap = rtl8723a_set_crystal_cap,
+       .cck_rssi = rtl8723b_cck_rssi,
        .writeN_block_size = 1024,
        .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
        .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
index 3bd9e5370b23c80d0fc6d7ebfdaa72c866130fb6..51cb22ee55cd51110c4f1e9bd47ab7e708a8da59 100644 (file)
@@ -4318,6 +4318,29 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
                val32 &= 0xfff00fff;
                val32 |= 0x0007e000;
                rtl8xxxu_write32(priv, REG_AFE_MISC, val32);
+
+               /*
+                * 0x824[9] = 0x82C[9] = 0xA80[7] those registers setting
+                * should be equal or CCK RSSI report may be incorrect
+                */
+               val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2);
+               priv->cck_agc_report_type = val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR;
+
+               val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_HSSI_PARM2);
+               if (priv->cck_agc_report_type != (bool)(val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR)) {
+                       if (priv->cck_agc_report_type)
+                               val32 |= FPGA0_HSSI_PARM2_CCK_HIGH_PWR;
+                       else
+                               val32 &= ~FPGA0_HSSI_PARM2_CCK_HIGH_PWR;
+                       rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM2, val32);
+               }
+
+               val32 = rtl8xxxu_read32(priv, REG_AGC_RPT);
+               if (priv->cck_agc_report_type)
+                       val32 |= AGC_RPT_CCK;
+               else
+                       val32 &= ~AGC_RPT_CCK;
+               rtl8xxxu_write32(priv, REG_AGC_RPT, val32);
        }
 
        /* Initialise the center frequency offset tracking */
@@ -5307,20 +5330,7 @@ static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
                 */
                u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
 
-               switch (cck_agc_rpt & 0xc0) {
-               case 0xc0:
-                       rx_status->signal = -46 - (cck_agc_rpt & 0x3e);
-                       break;
-               case 0x80:
-                       rx_status->signal = -26 - (cck_agc_rpt & 0x3e);
-                       break;
-               case 0x40:
-                       rx_status->signal = -12 - (cck_agc_rpt & 0x3e);
-                       break;
-               case 0x00:
-                       rx_status->signal = 16 - (cck_agc_rpt & 0x3e);
-                       break;
-               }
+               rx_status->signal = priv->fops->cck_rssi(priv, cck_agc_rpt);
        } else {
                bool parse_cfo = priv->fops->set_crystal_cap &&
                                 priv->vif &&
index 190bc0e8dc3349f42c19619b4ad06755576edf03..04bf77959fba9efeef7063eca2689221e78cfdbf 100644 (file)
 #define  CCK_PD_TYPE1_LV3_TH           0xdd
 #define  CCK_PD_TYPE1_LV4_TH           0xed
 
+#define REG_AGC_RPT                    0xa80
+#define  AGC_RPT_CCK                   BIT(7)
+
 #define REG_CONFIG_ANT_A               0x0b68
 #define REG_CONFIG_ANT_B               0x0b6c