diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 |
8 files changed, 117 insertions, 84 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index c25daec4f93d..f440ed0fe543 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -422,34 +422,6 @@ static void rs_free_sta(void *priv, struct ieee80211_sta *sta, } -/* - * get ieee prev rate from rate scale table. - * for A and B mode we need to overright prev - * value - */ -static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) -{ - int next_rate = iwl3945_get_prev_ieee_rate(rate); - - switch (priv->band) { - case IEEE80211_BAND_5GHZ: - if (rate == IWL_RATE_12M_INDEX) - next_rate = IWL_RATE_9M_INDEX; - else if (rate == IWL_RATE_6M_INDEX) - next_rate = IWL_RATE_6M_INDEX; - break; -/* XXX cannot be invoked in current mac80211 so not a regression - case MODE_IEEE80211B: - if (rate == IWL_RATE_11M_INDEX_TABLE) - next_rate = IWL_RATE_5M_INDEX_TABLE; - break; - */ - default: - break; - } - - return next_rate; -} /** * rs_tx_status - Update rate control values based on Tx results * @@ -460,17 +432,21 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { - u8 retries, current_count; + u8 retries = 0, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int i; IWL_DEBUG_RATE("enter\n"); - retries = info->status.retry_count; - first_index = sband->bitrates[info->tx_rate_idx].hw_value; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) + retries += info->status.rates[i].count; + retries--; + + first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; @@ -502,7 +478,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband last_index = scale_rate_index; } else { current_count = priv->retry_rate; - last_index = rs_adjust_next_rate(priv, + last_index = iwl3945_rs_next_rate(priv, scale_rate_index); } @@ -518,7 +494,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband if (retries) scale_rate_index = - rs_adjust_next_rate(priv, scale_rate_index); + iwl3945_rs_next_rate(priv, scale_rate_index); } @@ -630,10 +606,11 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * rate table and must reference the driver allocated rate table * */ -static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, + void *priv_sta, struct ieee80211_tx_rate_control *txrc) { + struct ieee80211_supported_band *sband = txrc->sband; + struct sk_buff *skb = txrc->skb; u8 low = IWL_RATE_INVALID; u8 high = IWL_RATE_INVALID; u16 high_low; @@ -649,6 +626,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 fc, rate_mask; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); @@ -659,7 +637,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -792,9 +770,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, rs_sta->last_txrate_idx = index; if (sband->band == IEEE80211_BAND_5GHZ) - sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; + info->control.rates[0].idx = rs_sta->last_txrate_idx - + IWL_FIRST_OFDM_RATE; else - sel->rate_idx = rs_sta->last_txrate_idx; + info->control.rates[0].idx = rs_sta->last_txrate_idx; IWL_DEBUG_RATE("leave: %d\n", index); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8a00245be51e..7afafb629706 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -261,6 +261,35 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status) } #endif +/* + * get ieee prev rate from rate scale table. + * for A and B mode we need to overright prev + * value + */ +int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) +{ + int next_rate = iwl3945_get_prev_ieee_rate(rate); + + switch (priv->band) { + case IEEE80211_BAND_5GHZ: + if (rate == IWL_RATE_12M_INDEX) + next_rate = IWL_RATE_9M_INDEX; + else if (rate == IWL_RATE_6M_INDEX) + next_rate = IWL_RATE_6M_INDEX; + break; +/* XXX cannot be invoked in current mac80211 so not a regression + case MODE_IEEE80211B: + if (rate == IWL_RATE_11M_INDEX_TABLE) + next_rate = IWL_RATE_5M_INDEX_TABLE; + break; + */ + default: + break; + } + + return next_rate; +} + /** * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd @@ -308,6 +337,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); int rate_idx; + int fail, i; if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " @@ -318,9 +348,36 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, } info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); + + /* Fill the MRR chain with some info about on-chip retransmissions */ + rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); + if (info->band == IEEE80211_BAND_5GHZ) + rate_idx -= IWL_FIRST_OFDM_RATE; + + fail = tx_resp->failure_frame; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + int next = iwl3945_rs_next_rate(priv, rate_idx); + + info->status.rates[i].idx = rate_idx; + + /* + * Put remaining into the last count as best approximation + * of saying exactly what the hardware would have done... + */ + if ((rate_idx == next) || (i == IEEE80211_TX_MAX_RATES - 1)) { + info->status.rates[i].count = fail; + break; + } + + info->status.rates[i].count = priv->retry_rate; + fail -= priv->retry_rate; + rate_idx = next; + if (fail <= 0) + break; + } + info->status.rates[i].count++; /* add final attempt */ - info->status.retry_count = tx_resp->failure_frame; /* tx_status->rts_retry_count = tx_resp->failure_rts; */ info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? IEEE80211_TX_STAT_ACK : 0; @@ -329,10 +386,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, txq_id, iwl3945_get_tx_fail_reason(status), status, tx_resp->rate, tx_resp->failure_frame); - rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); - if (info->band == IEEE80211_BAND_5GHZ) - rate_idx -= IWL_FIRST_OFDM_RATE; - info->tx_rate_idx = rate_idx; IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); iwl3945_tx_queue_reclaim(priv, txq_id, index); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index bdd32475b99c..592c5958723b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -954,6 +954,8 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch) extern const struct iwl3945_channel_info *iwl3945_get_channel_info( const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); +extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate); + /* Requires full declaration of iwl3945_priv before including */ #include "iwl-3945-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9838de5f4369..222c2baa95ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -619,10 +619,10 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { *tx_flags |= TX_CMD_FLG_RTS_MSK; *tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { *tx_flags &= ~TX_CMD_FLG_RTS_MSK; *tx_flags |= TX_CMD_FLG_CTS_MSK; } @@ -2070,7 +2070,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; @@ -2227,7 +2227,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags |= iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; iwl_hwrate_to_tx_control(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 56a3f0c84a1e..d5282fa65084 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -390,8 +390,8 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; else *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; @@ -1154,7 +1154,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; @@ -1307,7 +1307,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags = iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; iwl_hwrate_to_tx_control(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index e10e0ca09ce9..f685e5d6c281 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -798,7 +798,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - retries = info->status.retry_count; + retries = info->status.rates[0].count - 1; if (retries > 15) retries = 15; @@ -830,20 +830,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, if (priv->band == IEEE80211_BAND_5GHZ) rs_index -= IWL_FIRST_OFDM_RATE; - if ((info->tx_rate_idx < 0) || - (tbl_type.is_SGI ^ - !!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) || - (tbl_type.is_fat ^ - !!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) || - (tbl_type.is_dup ^ - !!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) || - (tbl_type.ant_type ^ info->antenna_sel_tx) || - (!!(tx_rate & RATE_MCS_HT_MSK) ^ - !!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) || - (!!(tx_rate & RATE_MCS_GF_MSK) ^ - !!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) || + if ((info->status.rates[0].idx < 0) || + (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || + (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || + (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || + (tbl_type.ant_type != info->antenna_sel_tx) || + (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || + (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != - hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) { + hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); goto out; } @@ -2098,15 +2093,17 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; } -static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc) { int i; + struct sk_buff *skb = txrc->skb; + struct ieee80211_supported_band *sband = txrc->sband; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); __le16 fc; struct iwl_lq_sta *lq_sta; @@ -2117,7 +2114,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -2143,13 +2140,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, } if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } if (sband->band == IEEE80211_BAND_5GHZ) i -= IWL_FIRST_OFDM_RATE; - sel->rate_idx = i; + info->control.rates[0].idx = i; } static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 10f5a0a233fe..2c4162e48140 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -88,26 +88,27 @@ EXPORT_SYMBOL(iwl_rates); * translate ucode response to mac80211 tx status control values */ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *control) + struct ieee80211_tx_info *info) { int rate_index; + struct ieee80211_tx_rate *r = &info->control.rates[0]; - control->antenna_sel_tx = + info->antenna_sel_tx = ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); if (rate_n_flags & RATE_MCS_HT_MSK) - control->flags |= IEEE80211_TX_CTL_OFDM_HT; + r->flags |= IEEE80211_TX_RC_MCS; if (rate_n_flags & RATE_MCS_GF_MSK) - control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; if (rate_n_flags & RATE_MCS_FAT_MSK) - control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; if (rate_n_flags & RATE_MCS_DUP_MSK) - control->flags |= IEEE80211_TX_CTL_DUP_DATA; + r->flags |= IEEE80211_TX_RC_DUP_DATA; if (rate_n_flags & RATE_MCS_SGI_MSK) - control->flags |= IEEE80211_TX_CTL_SHORT_GI; + r->flags |= IEEE80211_TX_RC_SHORT_GI; rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags); - if (control->band == IEEE80211_BAND_5GHZ) + if (info->band == IEEE80211_BAND_5GHZ) rate_index -= IWL_FIRST_OFDM_RATE; - control->tx_rate_idx = rate_index; + r->idx = rate_index; } EXPORT_SYMBOL(iwl_hwrate_to_tx_control); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b1464c71ea0a..2cd33b4e9e13 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2395,6 +2395,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, { __le16 fc = hdr->frame_control; __le32 tx_flags = cmd->cmd.tx.tx_flags; + u8 rc_flags = info->control.rates[0].flags; cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { @@ -2421,10 +2422,10 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { tx_flags |= TX_CMD_FLG_RTS_MSK; tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { tx_flags &= ~TX_CMD_FLG_RTS_MSK; tx_flags |= TX_CMD_FLG_CTS_MSK; } |