diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 208 |
1 files changed, 102 insertions, 106 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 1460116d329f..cf4a95bae4ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -295,11 +295,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) return tl->total; } -static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, +static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct iwl_lq_sta *lq_data, u8 tid, struct ieee80211_sta *sta) { - int ret; + int ret = -EAGAIN; if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", @@ -313,29 +313,29 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, */ IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", tid); - ret = ieee80211_stop_tx_ba_session(sta, tid, + ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); } - } + } else + IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); + return ret; } static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, struct iwl_lq_sta *lq_data, struct ieee80211_sta *sta) { - if ((tid < TID_MAX_LOAD_COUNT)) - rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); - else if (tid == IWL_AGG_ALL_TID) - for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) - rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); - if (priv->cfg->use_rts_for_ht) { - /* - * switch to RTS/CTS if it is the prefer protection method - * for HT traffic - */ - IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); - priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; - iwlcore_commit_rxon(priv); + if ((tid < TID_MAX_LOAD_COUNT) && + !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { + if (priv->cfg->use_rts_for_ht) { + /* + * switch to RTS/CTS if it is the prefer protection + * method for HT traffic + */ + IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); + priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; + iwlcore_commit_rxon(priv); + } } } @@ -611,10 +611,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, struct ieee80211_hdr *hdr, enum iwl_table_type rate_type) { - if (hdr && is_multicast_ether_addr(hdr->addr1) && - lq_sta->active_rate_basic) - return lq_sta->active_rate_basic; - if (is_legacy(rate_type)) { return lq_sta->active_legacy_rate; } else { @@ -775,6 +771,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); + /* Treat uninitialized rate scaling data same as non-existing. */ + if (!lq_sta) { + IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n"); + return; + } else if (!lq_sta->drv) { + IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); + return; + } + if (!ieee80211_is_data(hdr->frame_control) || info->flags & IEEE80211_TX_CTL_NO_ACK) return; @@ -784,10 +789,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !lq_sta->ibss_sta_added) - return; - /* * Ignore this Tx frame response if its initial rate doesn't match * that of latest Link Quality command. There may be stragglers @@ -833,7 +834,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter++; if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { lq_sta->missed_rate_counter = 0; - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); } /* Regardless, ignore this status info for outdated rate */ return; @@ -867,14 +868,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); rs_collect_tx_data(curr_tbl, rs_index, - info->status.ampdu_ack_len, - info->status.ampdu_ack_map); + info->status.ampdu_len, + info->status.ampdu_ack_len); /* Update success/fail counts if not searching for new mode */ if (lq_sta->stay_in_tbl) { - lq_sta->total_success += info->status.ampdu_ack_map; - lq_sta->total_failed += (info->status.ampdu_ack_len - - info->status.ampdu_ack_map); + lq_sta->total_success += info->status.ampdu_ack_len; + lq_sta->total_failed += (info->status.ampdu_len - + info->status.ampdu_ack_len); } } else { /* @@ -1913,7 +1914,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, /* Update uCode's rate table. */ rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rs_fill_link_cmd(priv, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); return rate; } @@ -2002,7 +2003,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* rates available for this association, and for modulation mode */ rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); - IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); + IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask); /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { @@ -2077,10 +2078,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, } /* Else we have enough samples; calculate estimate of * actual average throughput */ - - /* Sanity-check TPT calculations */ - BUG_ON(window->average_tpt != ((window->success_ratio * - tbl->expected_tpt[index] + 64) / 128)); + if (window->average_tpt != ((window->success_ratio * + tbl->expected_tpt[index] + 64) / 128)) { + IWL_ERR(priv, "expected_tpt should have been calculated by now\n"); + window->average_tpt = ((window->success_ratio * + tbl->expected_tpt[index] + 64) / 128); + } /* If we are searching for better modulation mode, check success. */ if (lq_sta->search_better_tbl && @@ -2289,7 +2292,7 @@ lq_update: IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", tbl->current_rate, index); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); } else done_search = 1; } @@ -2334,11 +2337,22 @@ out: tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); i = index; lq_sta->last_txrate_idx = i; - - return; } - +/** + * rs_initialize_lq - Initialize a station's hardware rate table + * + * The uCode's station table contains a table of fallback rates + * for automatic fallback during transmission. + * + * NOTE: This sets up a default set of values. These will be replaced later + * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of + * rc80211_simple. + * + * NOTE: Run REPLY_ADD_STA command to set up station table entry, before + * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, + * which requires station table entry to exist). + */ static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, struct ieee80211_sta *sta, @@ -2357,10 +2371,6 @@ static void rs_initialize_lq(struct iwl_priv *priv, i = lq_sta->last_txrate_idx; - if ((lq_sta->lq.sta_id == 0xff) && - (priv->iw_mode == NL80211_IFTYPE_ADHOC)) - goto out; - valid_tx_ant = priv->hw_params.valid_tx_ant; if (!lq_sta->search_better_tbl) @@ -2388,7 +2398,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, tbl->current_rate = rate; rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); out: return; } @@ -2399,10 +2410,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, 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_sta_ht_cap *ht_cap = &sta->ht_cap; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; @@ -2420,30 +2428,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, lq_sta->max_rate_idx = -1; } + /* Treat uninitialized rate scaling data same as non-existing. */ + if (lq_sta && !lq_sta->drv) { + IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); + priv_sta = NULL; + } + /* Send management frames and NO_ACK data using lowest rate. */ if (rate_control_send_low(sta, priv_sta, txrc)) return; rate_idx = lq_sta->last_txrate_idx; - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !lq_sta->ibss_sta_added) { - u8 sta_id = iwl_find_station(priv, hdr->addr1); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", - hdr->addr1); - sta_id = iwl_add_station(priv, hdr->addr1, - false, CMD_ASYNC, ht_cap); - } - if ((sta_id != IWL_INVALID_STATION)) { - lq_sta->lq.sta_id = sta_id; - lq_sta->lq.rs_table[0].rate_n_flags = 0; - lq_sta->ibss_sta_added = 1; - rs_initialize_lq(priv, conf, sta, lq_sta); - } - } - if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { rate_idx -= IWL_FIRST_OFDM_RATE; /* 6M and 9M shared same MCS index */ @@ -2493,16 +2489,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, return lq_sta; } -static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) +/* + * Called after adding a new station to initialize rate scaling + */ +void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) { int i, j; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct iwl_lq_sta *lq_sta = priv_sta; + struct iwl_station_priv *sta_priv; + struct iwl_lq_sta *lq_sta; + struct ieee80211_supported_band *sband; + + sta_priv = (struct iwl_station_priv *) sta->drv_priv; + lq_sta = &sta_priv->lq_sta; + sband = hw->wiphy->bands[conf->channel->band]; - lq_sta->lq.sta_id = 0xff; + + lq_sta->lq.sta_id = sta_id; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) @@ -2514,39 +2519,18 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); + IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", + sta_id); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately * after assoc.. */ - lq_sta->ibss_sta_added = 0; - if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, - sta->addr); - - /* for IBSS the call are from tasklet */ - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - sta_id = iwl_add_station(priv, sta->addr, false, - CMD_ASYNC, ht_cap); - } - if ((sta_id != IWL_INVALID_STATION)) { - lq_sta->lq.sta_id = sta_id; - lq_sta->lq.rs_table[0].rate_n_flags = 0; - } - /* FIXME: this is w/a remove it later */ - priv->assoc_station_added = 1; - } - lq_sta->is_dup = 0; lq_sta->max_rate_idx = -1; lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); - lq_sta->active_rate_basic = priv->active_rate_basic; lq_sta->band = priv->band; /* * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), @@ -2574,8 +2558,17 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->active_mimo3_rate); /* These values will be overridden later */ - lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; - lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; + lq_sta->lq.general_params.single_stream_ant_msk = + first_antenna(priv->hw_params.valid_tx_ant); + lq_sta->lq.general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); + if (!lq_sta->lq.general_params.dual_stream_ant_msk) { + lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { + lq_sta->lq.general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant; + } /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; @@ -2794,7 +2787,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, if (lq_sta->dbg_fixed_rate) { rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); } return count; @@ -2950,12 +2943,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, desc += sprintf(buff+desc, "Bit Rate= %d Mb/s\n", iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - desc += sprintf(buff+desc, - "Signal Level= %d dBm\tNoise Level= %d dBm\n", - priv->last_rx_rssi, priv->last_rx_noise); - desc += sprintf(buff+desc, - "Tsf= 0x%llx\tBeacon time= 0x%08X\n", - priv->last_tsf, priv->last_beacon_time); ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); return ret; @@ -2995,12 +2982,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) } #endif +/* + * Initialization of rate scaling information is done by driver after + * the station is added. Since mac80211 calls this function before a + * station is added we ignore it. + */ +static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) +{ +} static struct rate_control_ops rs_ops = { .module = NULL, .name = RS_NAME, .tx_status = rs_tx_status, .get_rate = rs_get_rate, - .rate_init = rs_rate_init, + .rate_init = rs_rate_init_stub, .alloc = rs_alloc, .free = rs_free, .alloc_sta = rs_alloc_sta, |