Commit 31513be8 authored by Daniel C Halperin's avatar Daniel C Halperin Committed by John W. Linville

iwlwifi: use iwl_hwrate_get_mac80211_idx where appropriate

For HT packets, mac80211 expects the rate_idx to be an MCS number, which is the
lower byte of rate_n_flags.  However, iwl_hwrate_to_plcp_idx takes the MCS
number and reduces it down to the range 0-8 (6 to 60 Mbps), removing the bits
that signify multiply streams, HT40 Duplicate mode, or unequal modulation.
This version is used for various internal purposes through the driver.

Add the function iwl_hwrate_get_mac80211_idx, an alternate version which takes
the rate and the band and returns the mac80211 index (MCS, for HT packets, and
PLCP rate, for legacy packets).
Signed-off-by: default avatarDaniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b58ef214
...@@ -878,6 +878,12 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, ...@@ -878,6 +878,12 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
rs_index -= IWL_FIRST_OFDM_RATE; rs_index -= IWL_FIRST_OFDM_RATE;
mac_flags = info->status.rates[0].flags; mac_flags = info->status.rates[0].flags;
mac_index = info->status.rates[0].idx; mac_index = info->status.rates[0].idx;
/* For HT packets, map MCS to PLCP */
if (mac_flags & IEEE80211_TX_RC_MCS) {
mac_index &= RATE_MCS_CODE_MSK; /* Remove # of streams */
if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
mac_index++;
}
if ((mac_index < 0) || if ((mac_index < 0) ||
(tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
...@@ -886,8 +892,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, ...@@ -886,8 +892,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
(tbl_type.ant_type != info->antenna_sel_tx) || (tbl_type.ant_type != info->antenna_sel_tx) ||
(!!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) || (!!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) ||
(!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
rs_index != mac_index) { (rs_index != mac_index)) {
IWL_DEBUG_RATE(priv, "initial rate does not match 0x%x\n", tx_rate); IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate);
/* the last LQ command could failed so the LQ in ucode not /* the last LQ command could failed so the LQ in ucode not
* the same in driver sync up * the same in driver sync up
*/ */
......
...@@ -96,7 +96,6 @@ EXPORT_SYMBOL(iwl_rates); ...@@ -96,7 +96,6 @@ EXPORT_SYMBOL(iwl_rates);
void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info) struct ieee80211_tx_info *info)
{ {
int rate_index;
struct ieee80211_tx_rate *r = &info->control.rates[0]; struct ieee80211_tx_rate *r = &info->control.rates[0];
info->antenna_sel_tx = info->antenna_sel_tx =
...@@ -111,10 +110,7 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, ...@@ -111,10 +110,7 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
r->flags |= IEEE80211_TX_RC_DUP_DATA; r->flags |= IEEE80211_TX_RC_DUP_DATA;
if (rate_n_flags & RATE_MCS_SGI_MSK) if (rate_n_flags & RATE_MCS_SGI_MSK)
r->flags |= IEEE80211_TX_RC_SHORT_GI; r->flags |= IEEE80211_TX_RC_SHORT_GI;
rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags); r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band);
if (info->band == IEEE80211_BAND_5GHZ)
rate_index -= IWL_FIRST_OFDM_RATE;
r->idx = rate_index;
} }
EXPORT_SYMBOL(iwl_hwrate_to_tx_control); EXPORT_SYMBOL(iwl_hwrate_to_tx_control);
...@@ -149,6 +145,27 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) ...@@ -149,6 +145,27 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
} }
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
{
int idx = 0;
int band_offset = 0;
/* HT rate format: mac80211 wants an MCS number, which is just LSB */
if (rate_n_flags & RATE_MCS_HT_MSK) {
idx = (rate_n_flags & 0xff);
return idx;
/* Legacy rate format, search for match in table */
} else {
if (band == IEEE80211_BAND_5GHZ)
band_offset = IWL_FIRST_OFDM_RATE;
for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
return idx - band_offset;
}
return -1;
}
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
{ {
int i; int i;
......
...@@ -423,6 +423,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); ...@@ -423,6 +423,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info); struct ieee80211_tx_info *info);
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
......
...@@ -962,6 +962,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, ...@@ -962,6 +962,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
return; return;
} }
/* This will be used in several places later */
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
/* rx_status carries information about the packet to mac80211 */ /* rx_status carries information about the packet to mac80211 */
rx_status.mactime = le64_to_cpu(phy_res->timestamp); rx_status.mactime = le64_to_cpu(phy_res->timestamp);
rx_status.freq = rx_status.freq =
...@@ -969,10 +972,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, ...@@ -969,10 +972,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
rx_status.rate_idx = rx_status.rate_idx =
iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags)); iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
if (rx_status.band == IEEE80211_BAND_5GHZ)
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
rx_status.flag = 0; rx_status.flag = 0;
/* TSF isn't reliable. In order to allow smooth user experience, /* TSF isn't reliable. In order to allow smooth user experience,
...@@ -1034,7 +1034,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, ...@@ -1034,7 +1034,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
rx_status.flag |= RX_FLAG_SHORTPRE; rx_status.flag |= RX_FLAG_SHORTPRE;
/* Set up the HT phy flags */ /* Set up the HT phy flags */
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
if (rate_n_flags & RATE_MCS_HT_MSK) if (rate_n_flags & RATE_MCS_HT_MSK)
rx_status.flag |= RX_FLAG_HT; rx_status.flag |= RX_FLAG_HT;
if (rate_n_flags & RATE_MCS_HT40_MSK) if (rate_n_flags & RATE_MCS_HT40_MSK)
......
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