diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 111 |
1 files changed, 62 insertions, 49 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7bc9c0039f7..a7422e52d88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -566,62 +566,81 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, - __le16 fc, int sta_id, - int is_hcca) + __le16 fc, int is_hcca) { - u32 rate_flags = 0; + u32 rate_flags; int rate_idx; - u8 rts_retry_limit = 0; - u8 data_retry_limit = 0; + u8 rts_retry_limit; + u8 data_retry_limit; u8 rate_plcp; - rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff, - IWL_RATE_COUNT - 1); - - rate_plcp = iwl_rates[rate_idx].plcp; - - rts_retry_limit = (is_hcca) ? - RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT; - - if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) - rate_flags |= RATE_MCS_CCK_MSK; - - - if (ieee80211_is_probe_resp(fc)) { - data_retry_limit = 3; - if (data_retry_limit < rts_retry_limit) - rts_retry_limit = data_retry_limit; - } else - data_retry_limit = IWL_DEFAULT_TX_RETRY; - + /* Set retry limit on DATA packets and Probe Responses*/ if (priv->data_retry_limit != -1) data_retry_limit = priv->data_retry_limit; + else if (ieee80211_is_probe_resp(fc)) + data_retry_limit = 3; + else + data_retry_limit = IWL_DEFAULT_TX_RETRY; + tx_cmd->data_retry_limit = data_retry_limit; + /* Set retry limit on RTS packets */ + rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT : + RTS_DFAULT_RETRY_LIMIT; + if (data_retry_limit < rts_retry_limit) + rts_retry_limit = data_retry_limit; + tx_cmd->rts_retry_limit = rts_retry_limit; + /* DATA packets will use the uCode station table for rate/antenna + * selection */ if (ieee80211_is_data(fc)) { tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; - } else { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { - tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; - } - break; - default: - break; - } + return; + } + + /** + * If the current TX rate stored in mac80211 has the MCS bit set, it's + * not really a TX rate. Thus, we use the lowest supported rate for + * this band. Also use the lowest supported rate if the stored rate + * index is invalid. + */ + rate_idx = info->control.rates[0].idx; + if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || + (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) + rate_idx = rate_lowest_index(&priv->bands[info->band], + info->control.sta); + /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ + if (info->band == IEEE80211_BAND_5GHZ) + rate_idx += IWL_FIRST_OFDM_RATE; + /* Get PLCP rate for tx_cmd->rate_n_flags */ + rate_plcp = iwl_rates[rate_idx].plcp; + /* Zero out flags for this packet */ + rate_flags = 0; - priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); - rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); + /* Set CCK flag as needed */ + if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) + rate_flags |= RATE_MCS_CCK_MSK; + + /* Set up RTS and CTS flags for certain packets */ + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): + if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { + tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; + tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; + } + break; + default: + break; } - tx_cmd->rts_retry_limit = rts_retry_limit; - tx_cmd->data_retry_limit = data_retry_limit; + /* Set up antennas */ + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); + rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); + + /* Set the rate in the TX cmd */ tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); } @@ -701,12 +720,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) goto drop_unlock; } - if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == - IWL_INVALID_RATE) { - IWL_ERR(priv, "ERROR: No TX rate available.\n"); - goto drop_unlock; - } - fc = hdr->frame_control; #ifdef CONFIG_IWLWIFI_DEBUG @@ -807,7 +820,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_dbg_log_tx_data_frame(priv, len, hdr); /* set is_hcca to 0; it probably will never be implemented */ - iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0); + iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0); iwl_update_stats(priv, true, fc, len); /* |