Commit 8101a7f0 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg

iwlwifi: mvm: update the rssi calculation

Make the rssi more accurate by taking in count per-chain AGC
values. Without this, the RSSI reports inaccurate values.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f9aa8dd3
...@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd { ...@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd {
#define IWL_RX_INFO_PHY_CNT 8 #define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_AGC_IDX 1 #define IWL_RX_INFO_AGC_IDX 1
#define IWL_RX_INFO_RSSI_AB_IDX 2 #define IWL_RX_INFO_RSSI_AB_IDX 2
#define IWL_RX_INFO_RSSI_C_IDX 3 #define IWL_OFDM_AGC_A_MSK 0x0000007f
#define IWL_OFDM_AGC_DB_MSK 0xfe00 #define IWL_OFDM_AGC_A_POS 0
#define IWL_OFDM_AGC_DB_POS 9 #define IWL_OFDM_AGC_B_MSK 0x00003f80
#define IWL_OFDM_AGC_B_POS 7
#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000
#define IWL_OFDM_AGC_CODE_POS 20
#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
#define IWL_OFDM_RSSI_A_POS 0 #define IWL_OFDM_RSSI_A_POS 0
#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
#define IWL_OFDM_RSSI_ALLBAND_A_POS 8
#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
#define IWL_OFDM_RSSI_B_POS 16 #define IWL_OFDM_RSSI_B_POS 16
#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff #define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00 #define IWL_OFDM_RSSI_ALLBAND_B_POS 24
#define IWL_OFDM_RSSI_C_POS 0
/** /**
* struct iwl_rx_phy_info - phy info * struct iwl_rx_phy_info - phy info
......
...@@ -80,7 +80,8 @@ ...@@ -80,7 +80,8 @@
#define IWL_INVALID_MAC80211_QUEUE 0xff #define IWL_INVALID_MAC80211_QUEUE 0xff
#define IWL_MVM_MAX_ADDRESSES 2 #define IWL_MVM_MAX_ADDRESSES 2
#define IWL_RSSI_OFFSET 44 /* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
enum iwl_mvm_tx_fifo { enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_BK = 0, IWL_MVM_TX_FIFO_BK = 0,
......
...@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, ...@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
struct iwl_rx_phy_info *phy_info) struct iwl_rx_phy_info *phy_info)
{ {
u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db; int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
int rssi_all_band_a, rssi_all_band_b;
u32 agc_a, agc_b, max_agc;
u32 val; u32 val;
/* Find max rssi among 3 possible receivers. /* Find max rssi among 2 possible receivers.
* These values are measured by the Digital Signal Processor (DSP). * These values are measured by the Digital Signal Processor (DSP).
* They should stay fairly constant even as the signal strength varies, * They should stay fairly constant even as the signal strength varies,
* if the radio's Automatic Gain Control (AGC) is working right. * if the radio's Automatic Gain Control (AGC) is working right.
* AGC value (see below) will provide the "interesting" info. * AGC value (see below) will provide the "interesting" info.
*/ */
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
max_agc = max_t(u32, agc_a, agc_b);
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]); rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS; IWL_OFDM_RSSI_ALLBAND_A_POS;
rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); IWL_OFDM_RSSI_ALLBAND_B_POS;
agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS;
max_rssi = max_t(u32, rssi_a, rssi_b); /*
max_rssi = max_t(u32, max_rssi, rssi_c); * dBm = rssi dB - agc dB - constant.
* Higher AGC (higher radio gain) means lower signal.
*/
rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a;
rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b;
max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm);
IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
rssi_a, rssi_b, rssi_c, max_rssi, agc_db); rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
/* dBm = max_rssi dB - agc dB - constant. return max_rssi_dbm;
* Higher AGC (higher radio gain) means lower signal. */
return max_rssi - agc_db - IWL_RSSI_OFFSET;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment