Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd {
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_AGC_IDX 1
#define IWL_RX_INFO_RSSI_AB_IDX 2
#define IWL_RX_INFO_RSSI_C_IDX 3
#define IWL_OFDM_AGC_DB_MSK 0xfe00
#define IWL_OFDM_AGC_DB_POS 9
#define IWL_OFDM_AGC_A_MSK 0x0000007f
#define IWL_OFDM_AGC_A_POS 0
#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_ALLBAND_A_MSK 0xff00
#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_ALLBAND_B_MSK 0xff000000
#define IWL_OFDM_RSSI_B_POS 16
#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff
#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00
#define IWL_OFDM_RSSI_C_POS 0
#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
#define IWL_OFDM_RSSI_ALLBAND_B_POS 24

/**
 * struct iwl_rx_phy_info - phy info
+2 −1
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@

#define IWL_INVALID_MAC80211_QUEUE	0xff
#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 {
	IWL_MVM_TX_FIFO_BK = 0,
+23 −14
Original line number Diff line number Diff line
@@ -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,
			     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;

	/* Find max rssi among 3 possible receivers.
	/* Find max rssi among 2 possible receivers.
	 * These values are measured by the Digital Signal Processor (DSP).
	 * They should stay fairly constant even as the signal strength varies,
	 * if the radio's Automatic Gain Control (AGC) is working right.
	 * 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]);
	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;
	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]);
	rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS;

	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
	agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS;
	rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
				IWL_OFDM_RSSI_ALLBAND_A_POS;
	rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
				IWL_OFDM_RSSI_ALLBAND_B_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",
			rssi_a, rssi_b, rssi_c, max_rssi, agc_db);
	IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
			rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);

	/* dBm = max_rssi dB - agc dB - constant.
	 * Higher AGC (higher radio gain) means lower signal. */
	return max_rssi - agc_db - IWL_RSSI_OFFSET;
	return max_rssi_dbm;
}

/*