diff options
author | David S. Miller <davem@davemloft.net> | 2010-03-29 16:50:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-29 16:50:10 -0400 |
commit | 7905e357ebe67a26d9dc8caa1a0b8346431b5f0d (patch) | |
tree | 134442df2f062caa6cebda1b352948b8209efcec /drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |
parent | 083ba279d52bcad20f1dfa3cefd4255cbe82d521 (diff) | |
parent | 76232ebf898c4d5e657f2b663fbf7108bca80ded (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 124 |
1 files changed, 61 insertions, 63 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 84271cc62af..5155b1a027e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -769,6 +769,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
769 | 769 | ||
770 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 770 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
771 | 771 | ||
772 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
773 | if (!lq_sta) { | ||
774 | IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n"); | ||
775 | return; | ||
776 | } else if (!lq_sta->drv) { | ||
777 | IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); | ||
778 | return; | ||
779 | } | ||
780 | |||
772 | if (!ieee80211_is_data(hdr->frame_control) || | 781 | if (!ieee80211_is_data(hdr->frame_control) || |
773 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 782 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
774 | return; | 783 | return; |
@@ -778,10 +787,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
778 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 787 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
779 | return; | 788 | return; |
780 | 789 | ||
781 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
782 | !lq_sta->ibss_sta_added) | ||
783 | return; | ||
784 | |||
785 | /* | 790 | /* |
786 | * Ignore this Tx frame response if its initial rate doesn't match | 791 | * Ignore this Tx frame response if its initial rate doesn't match |
787 | * that of latest Link Quality command. There may be stragglers | 792 | * that of latest Link Quality command. There may be stragglers |
@@ -827,7 +832,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
827 | lq_sta->missed_rate_counter++; | 832 | lq_sta->missed_rate_counter++; |
828 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 833 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
829 | lq_sta->missed_rate_counter = 0; | 834 | lq_sta->missed_rate_counter = 0; |
830 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 835 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
831 | } | 836 | } |
832 | /* Regardless, ignore this status info for outdated rate */ | 837 | /* Regardless, ignore this status info for outdated rate */ |
833 | return; | 838 | return; |
@@ -1915,7 +1920,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, | |||
1915 | /* Update uCode's rate table. */ | 1920 | /* Update uCode's rate table. */ |
1916 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); | 1921 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); |
1917 | rs_fill_link_cmd(priv, lq_sta, rate); | 1922 | rs_fill_link_cmd(priv, lq_sta, rate); |
1918 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 1923 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
1919 | 1924 | ||
1920 | return rate; | 1925 | return rate; |
1921 | } | 1926 | } |
@@ -2291,7 +2296,7 @@ lq_update: | |||
2291 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", | 2296 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", |
2292 | tbl->current_rate, index); | 2297 | tbl->current_rate, index); |
2293 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); | 2298 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); |
2294 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2299 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
2295 | } else | 2300 | } else |
2296 | done_search = 1; | 2301 | done_search = 1; |
2297 | } | 2302 | } |
@@ -2340,7 +2345,20 @@ out: | |||
2340 | return; | 2345 | return; |
2341 | } | 2346 | } |
2342 | 2347 | ||
2343 | 2348 | /** | |
2349 | * rs_initialize_lq - Initialize a station's hardware rate table | ||
2350 | * | ||
2351 | * The uCode's station table contains a table of fallback rates | ||
2352 | * for automatic fallback during transmission. | ||
2353 | * | ||
2354 | * NOTE: This sets up a default set of values. These will be replaced later | ||
2355 | * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of | ||
2356 | * rc80211_simple. | ||
2357 | * | ||
2358 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
2359 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
2360 | * which requires station table entry to exist). | ||
2361 | */ | ||
2344 | static void rs_initialize_lq(struct iwl_priv *priv, | 2362 | static void rs_initialize_lq(struct iwl_priv *priv, |
2345 | struct ieee80211_conf *conf, | 2363 | struct ieee80211_conf *conf, |
2346 | struct ieee80211_sta *sta, | 2364 | struct ieee80211_sta *sta, |
@@ -2359,10 +2377,6 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2359 | 2377 | ||
2360 | i = lq_sta->last_txrate_idx; | 2378 | i = lq_sta->last_txrate_idx; |
2361 | 2379 | ||
2362 | if ((lq_sta->lq.sta_id == 0xff) && | ||
2363 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) | ||
2364 | goto out; | ||
2365 | |||
2366 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2380 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2367 | 2381 | ||
2368 | if (!lq_sta->search_better_tbl) | 2382 | if (!lq_sta->search_better_tbl) |
@@ -2390,7 +2404,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2390 | tbl->current_rate = rate; | 2404 | tbl->current_rate = rate; |
2391 | rs_set_expected_tpt_table(lq_sta, tbl); | 2405 | rs_set_expected_tpt_table(lq_sta, tbl); |
2392 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2406 | rs_fill_link_cmd(NULL, lq_sta, rate); |
2393 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2407 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; |
2408 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); | ||
2394 | out: | 2409 | out: |
2395 | return; | 2410 | return; |
2396 | } | 2411 | } |
@@ -2402,9 +2417,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2402 | struct sk_buff *skb = txrc->skb; | 2417 | struct sk_buff *skb = txrc->skb; |
2403 | struct ieee80211_supported_band *sband = txrc->sband; | 2418 | struct ieee80211_supported_band *sband = txrc->sband; |
2404 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2419 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2405 | struct ieee80211_conf *conf = &priv->hw->conf; | ||
2406 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
2408 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2420 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2409 | struct iwl_lq_sta *lq_sta = priv_sta; | 2421 | struct iwl_lq_sta *lq_sta = priv_sta; |
2410 | int rate_idx; | 2422 | int rate_idx; |
@@ -2422,30 +2434,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2422 | lq_sta->max_rate_idx = -1; | 2434 | lq_sta->max_rate_idx = -1; |
2423 | } | 2435 | } |
2424 | 2436 | ||
2437 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
2438 | if (lq_sta && !lq_sta->drv) { | ||
2439 | IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); | ||
2440 | priv_sta = NULL; | ||
2441 | } | ||
2442 | |||
2425 | /* Send management frames and NO_ACK data using lowest rate. */ | 2443 | /* Send management frames and NO_ACK data using lowest rate. */ |
2426 | if (rate_control_send_low(sta, priv_sta, txrc)) | 2444 | if (rate_control_send_low(sta, priv_sta, txrc)) |
2427 | return; | 2445 | return; |
2428 | 2446 | ||
2429 | rate_idx = lq_sta->last_txrate_idx; | 2447 | rate_idx = lq_sta->last_txrate_idx; |
2430 | 2448 | ||
2431 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
2432 | !lq_sta->ibss_sta_added) { | ||
2433 | u8 sta_id = iwl_find_station(priv, hdr->addr1); | ||
2434 | |||
2435 | if (sta_id == IWL_INVALID_STATION) { | ||
2436 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", | ||
2437 | hdr->addr1); | ||
2438 | sta_id = iwl_add_station(priv, hdr->addr1, | ||
2439 | false, CMD_ASYNC, ht_cap); | ||
2440 | } | ||
2441 | if ((sta_id != IWL_INVALID_STATION)) { | ||
2442 | lq_sta->lq.sta_id = sta_id; | ||
2443 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | ||
2444 | lq_sta->ibss_sta_added = 1; | ||
2445 | rs_initialize_lq(priv, conf, sta, lq_sta); | ||
2446 | } | ||
2447 | } | ||
2448 | |||
2449 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { | 2449 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { |
2450 | rate_idx -= IWL_FIRST_OFDM_RATE; | 2450 | rate_idx -= IWL_FIRST_OFDM_RATE; |
2451 | /* 6M and 9M shared same MCS index */ | 2451 | /* 6M and 9M shared same MCS index */ |
@@ -2495,16 +2495,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | |||
2495 | return lq_sta; | 2495 | return lq_sta; |
2496 | } | 2496 | } |
2497 | 2497 | ||
2498 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | 2498 | /* |
2499 | struct ieee80211_sta *sta, void *priv_sta) | 2499 | * Called after adding a new station to initialize rate scaling |
2500 | */ | ||
2501 | void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) | ||
2500 | { | 2502 | { |
2501 | int i, j; | 2503 | int i, j; |
2502 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2504 | struct ieee80211_hw *hw = priv->hw; |
2503 | struct ieee80211_conf *conf = &priv->hw->conf; | 2505 | struct ieee80211_conf *conf = &priv->hw->conf; |
2504 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2506 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
2505 | struct iwl_lq_sta *lq_sta = priv_sta; | 2507 | struct iwl_station_priv *sta_priv; |
2508 | struct iwl_lq_sta *lq_sta; | ||
2509 | struct ieee80211_supported_band *sband; | ||
2510 | |||
2511 | sta_priv = (struct iwl_station_priv *) sta->drv_priv; | ||
2512 | lq_sta = &sta_priv->lq_sta; | ||
2513 | sband = hw->wiphy->bands[conf->channel->band]; | ||
2514 | |||
2506 | 2515 | ||
2507 | lq_sta->lq.sta_id = 0xff; | 2516 | lq_sta->lq.sta_id = sta_id; |
2508 | 2517 | ||
2509 | for (j = 0; j < LQ_SIZE; j++) | 2518 | for (j = 0; j < LQ_SIZE; j++) |
2510 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2519 | for (i = 0; i < IWL_RATE_COUNT; i++) |
@@ -2516,33 +2525,13 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2516 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2525 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2517 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2526 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
2518 | 2527 | ||
2519 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); | 2528 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", |
2529 | sta_id); | ||
2520 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 2530 | /* TODO: what is a good starting rate for STA? About middle? Maybe not |
2521 | * the lowest or the highest rate.. Could consider using RSSI from | 2531 | * the lowest or the highest rate.. Could consider using RSSI from |
2522 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 2532 | * previous packets? Need to have IEEE 802.1X auth succeed immediately |
2523 | * after assoc.. */ | 2533 | * after assoc.. */ |
2524 | 2534 | ||
2525 | lq_sta->ibss_sta_added = 0; | ||
2526 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | ||
2527 | u8 sta_id = iwl_find_station(priv, | ||
2528 | sta->addr); | ||
2529 | |||
2530 | /* for IBSS the call are from tasklet */ | ||
2531 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | ||
2532 | |||
2533 | if (sta_id == IWL_INVALID_STATION) { | ||
2534 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | ||
2535 | sta_id = iwl_add_station(priv, sta->addr, false, | ||
2536 | CMD_ASYNC, ht_cap); | ||
2537 | } | ||
2538 | if ((sta_id != IWL_INVALID_STATION)) { | ||
2539 | lq_sta->lq.sta_id = sta_id; | ||
2540 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | ||
2541 | } | ||
2542 | /* FIXME: this is w/a remove it later */ | ||
2543 | priv->assoc_station_added = 1; | ||
2544 | } | ||
2545 | |||
2546 | lq_sta->is_dup = 0; | 2535 | lq_sta->is_dup = 0; |
2547 | lq_sta->max_rate_idx = -1; | 2536 | lq_sta->max_rate_idx = -1; |
2548 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2537 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
@@ -2795,7 +2784,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2795 | 2784 | ||
2796 | if (lq_sta->dbg_fixed_rate) { | 2785 | if (lq_sta->dbg_fixed_rate) { |
2797 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 2786 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); |
2798 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); | 2787 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); |
2799 | } | 2788 | } |
2800 | 2789 | ||
2801 | return count; | 2790 | return count; |
@@ -2992,12 +2981,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) | |||
2992 | } | 2981 | } |
2993 | #endif | 2982 | #endif |
2994 | 2983 | ||
2984 | /* | ||
2985 | * Initialization of rate scaling information is done by driver after | ||
2986 | * the station is added. Since mac80211 calls this function before a | ||
2987 | * station is added we ignore it. | ||
2988 | */ | ||
2989 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | ||
2990 | struct ieee80211_sta *sta, void *priv_sta) | ||
2991 | { | ||
2992 | } | ||
2995 | static struct rate_control_ops rs_ops = { | 2993 | static struct rate_control_ops rs_ops = { |
2996 | .module = NULL, | 2994 | .module = NULL, |
2997 | .name = RS_NAME, | 2995 | .name = RS_NAME, |
2998 | .tx_status = rs_tx_status, | 2996 | .tx_status = rs_tx_status, |
2999 | .get_rate = rs_get_rate, | 2997 | .get_rate = rs_get_rate, |
3000 | .rate_init = rs_rate_init, | 2998 | .rate_init = rs_rate_init_stub, |
3001 | .alloc = rs_alloc, | 2999 | .alloc = rs_alloc, |
3002 | .free = rs_free, | 3000 | .free = rs_free, |
3003 | .alloc_sta = rs_alloc_sta, | 3001 | .alloc_sta = rs_alloc_sta, |