diff options
author | Abhijeet Kolekar <abhijeet.kolekar@intel.com> | 2009-03-11 14:17:56 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-16 18:09:46 -0400 |
commit | dd5b687edacab6cfacf7b9983e86a60c0612e994 (patch) | |
tree | 9c6458bfe9e40666d5ca5e69b38496dae14b565c /drivers/net/wireless | |
parent | 5c8df2d56a160a31386ee7807adfc1c74e826535 (diff) |
iwl3945 : fix rate scaling
Patch fixes the bug 1900 at
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1900
Issues:
Throughput and success ratio calculations were not done properly.
Number of retries were exceeding 16.
Fix:
Patch fixes above issues by doing window calculations inline with iwlwifi
Patch adds sanity check to limit number of retries to 16.
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Acked-by: Mohamed Abbas <mohamed.abbas@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 127 |
1 files changed, 88 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a2664589c88..f65c308a671 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -127,6 +127,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { | |||
127 | #define IWL_RATE_MIN_FAILURE_TH 8 | 127 | #define IWL_RATE_MIN_FAILURE_TH 8 |
128 | #define IWL_RATE_MIN_SUCCESS_TH 8 | 128 | #define IWL_RATE_MIN_SUCCESS_TH 8 |
129 | #define IWL_RATE_DECREASE_TH 1920 | 129 | #define IWL_RATE_DECREASE_TH 1920 |
130 | #define IWL_RATE_RETRY_TH 15 | ||
130 | 131 | ||
131 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) | 132 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) |
132 | { | 133 | { |
@@ -298,37 +299,53 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
298 | } | 299 | } |
299 | 300 | ||
300 | spin_lock_irqsave(&rs_sta->lock, flags); | 301 | spin_lock_irqsave(&rs_sta->lock, flags); |
301 | while (retries--) { | ||
302 | 302 | ||
303 | /* If we have filled up the window then subtract one from the | 303 | /* |
304 | * success counter if the high-bit is counting toward | 304 | * Keep track of only the latest 62 tx frame attempts in this rate's |
305 | * success */ | 305 | * history window; anything older isn't really relevant any more. |
306 | if (window->counter == IWL_RATE_MAX_WINDOW) { | 306 | * If we have filled up the sliding window, drop the oldest attempt; |
307 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) | 307 | * if the oldest attempt (highest bit in bitmap) shows "success", |
308 | * subtract "1" from the success counter (this is the main reason | ||
309 | * we keep these bitmaps!). | ||
310 | * */ | ||
311 | while (retries > 0) { | ||
312 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | ||
313 | |||
314 | /* remove earliest */ | ||
315 | window->counter = IWL_RATE_MAX_WINDOW - 1; | ||
316 | |||
317 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { | ||
318 | window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); | ||
308 | window->success_counter--; | 319 | window->success_counter--; |
309 | } else | 320 | } |
310 | window->counter++; | 321 | } |
311 | 322 | ||
312 | /* Slide the window to the left one bit */ | 323 | /* Increment frames-attempted counter */ |
313 | window->data = (window->data << 1); | 324 | window->counter++; |
314 | 325 | ||
315 | /* If this packet was a success then set the low bit high */ | 326 | /* Shift bitmap by one frame (throw away oldest history), |
316 | if (success) { | 327 | * OR in "1", and increment "success" if this |
328 | * frame was successful. */ | ||
329 | window->data <<= 1; | ||
330 | if (success > 0) { | ||
317 | window->success_counter++; | 331 | window->success_counter++; |
318 | window->data |= 1; | 332 | window->data |= 0x1; |
333 | success--; | ||
319 | } | 334 | } |
320 | 335 | ||
321 | /* window->counter can't be 0 -- it is either >0 or | 336 | retries--; |
322 | * IWL_RATE_MAX_WINDOW */ | ||
323 | window->success_ratio = 12800 * window->success_counter / | ||
324 | window->counter; | ||
325 | |||
326 | /* Tag this window as having been updated */ | ||
327 | window->stamp = jiffies; | ||
328 | |||
329 | } | 337 | } |
330 | 338 | ||
339 | /* Calculate current success ratio, avoid divide-by-0! */ | ||
340 | if (window->counter > 0) | ||
341 | window->success_ratio = 128 * (100 * window->success_counter) | ||
342 | / window->counter; | ||
343 | else | ||
344 | window->success_ratio = IWL_INVALID_VALUE; | ||
345 | |||
331 | fail_count = window->counter - window->success_counter; | 346 | fail_count = window->counter - window->success_counter; |
347 | |||
348 | /* Calculate average throughput, if we have enough history. */ | ||
332 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || | 349 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || |
333 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) | 350 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) |
334 | window->average_tpt = ((window->success_ratio * | 351 | window->average_tpt = ((window->success_ratio * |
@@ -336,6 +353,9 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
336 | else | 353 | else |
337 | window->average_tpt = IWL_INVALID_VALUE; | 354 | window->average_tpt = IWL_INVALID_VALUE; |
338 | 355 | ||
356 | /* Tag this window as having been updated */ | ||
357 | window->stamp = jiffies; | ||
358 | |||
339 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 359 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
340 | 360 | ||
341 | } | 361 | } |
@@ -468,7 +488,10 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband | |||
468 | 488 | ||
469 | IWL_DEBUG_RATE(priv, "enter\n"); | 489 | IWL_DEBUG_RATE(priv, "enter\n"); |
470 | 490 | ||
471 | retries = info->status.rates[0].count; | 491 | retries = info->status.rates[0].count - 1; |
492 | /* Sanity Check for retries */ | ||
493 | if (retries > IWL_RATE_RETRY_TH) | ||
494 | retries = IWL_RATE_RETRY_TH; | ||
472 | 495 | ||
473 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; | 496 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; |
474 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { | 497 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { |
@@ -724,7 +747,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
724 | 747 | ||
725 | fail_count = window->counter - window->success_counter; | 748 | fail_count = window->counter - window->success_counter; |
726 | 749 | ||
727 | if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && | 750 | if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && |
728 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { | 751 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { |
729 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 752 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
730 | 753 | ||
@@ -735,6 +758,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
735 | window->counter, | 758 | window->counter, |
736 | window->success_counter, | 759 | window->success_counter, |
737 | rs_sta->expected_tpt ? "not " : ""); | 760 | rs_sta->expected_tpt ? "not " : ""); |
761 | |||
762 | /* Can't calculate this yet; not enough history */ | ||
763 | window->average_tpt = IWL_INVALID_VALUE; | ||
738 | goto out; | 764 | goto out; |
739 | 765 | ||
740 | } | 766 | } |
@@ -750,6 +776,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
750 | if ((max_rate_idx != -1) && (max_rate_idx < high)) | 776 | if ((max_rate_idx != -1) && (max_rate_idx < high)) |
751 | high = IWL_RATE_INVALID; | 777 | high = IWL_RATE_INVALID; |
752 | 778 | ||
779 | /* Collect Measured throughputs of adjacent rates */ | ||
753 | if (low != IWL_RATE_INVALID) | 780 | if (low != IWL_RATE_INVALID) |
754 | low_tpt = rs_sta->win[low].average_tpt; | 781 | low_tpt = rs_sta->win[low].average_tpt; |
755 | 782 | ||
@@ -758,24 +785,43 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
758 | 785 | ||
759 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 786 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
760 | 787 | ||
761 | scale_action = 1; | 788 | scale_action = 0; |
762 | 789 | ||
790 | /* Low success ratio , need to drop the rate */ | ||
763 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { | 791 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { |
764 | IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); | 792 | IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); |
765 | scale_action = -1; | 793 | scale_action = -1; |
794 | |||
795 | /* No throughput measured yet for adjacent rates, | ||
796 | * try increase */ | ||
766 | } else if ((low_tpt == IWL_INVALID_VALUE) && | 797 | } else if ((low_tpt == IWL_INVALID_VALUE) && |
767 | (high_tpt == IWL_INVALID_VALUE)) | 798 | (high_tpt == IWL_INVALID_VALUE)) { |
768 | scale_action = 1; | 799 | |
769 | else if ((low_tpt != IWL_INVALID_VALUE) && | 800 | if (high != IWL_RATE_INVALID && window->success_counter >= IWL_RATE_INCREASE_TH) |
801 | scale_action = 1; | ||
802 | else if (low != IWL_RATE_INVALID) | ||
803 | scale_action = -1; | ||
804 | |||
805 | /* Both adjacent throughputs are measured, but neither one has | ||
806 | * better throughput; we're using the best rate, don't change | ||
807 | * it! */ | ||
808 | } else if ((low_tpt != IWL_INVALID_VALUE) && | ||
770 | (high_tpt != IWL_INVALID_VALUE) && | 809 | (high_tpt != IWL_INVALID_VALUE) && |
771 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { | 810 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { |
811 | |||
772 | IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " | 812 | IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " |
773 | "current_tpt [%d]\n", | 813 | "current_tpt [%d]\n", |
774 | low_tpt, high_tpt, current_tpt); | 814 | low_tpt, high_tpt, current_tpt); |
775 | scale_action = 0; | 815 | scale_action = 0; |
816 | |||
817 | /* At least one of the rates has better throughput */ | ||
776 | } else { | 818 | } else { |
777 | if (high_tpt != IWL_INVALID_VALUE) { | 819 | if (high_tpt != IWL_INVALID_VALUE) { |
778 | if (high_tpt > current_tpt) | 820 | |
821 | /* High rate has better throughput, Increase | ||
822 | * rate */ | ||
823 | if (high_tpt > current_tpt && | ||
824 | window->success_ratio >= IWL_RATE_INCREASE_TH) | ||
779 | scale_action = 1; | 825 | scale_action = 1; |
780 | else { | 826 | else { |
781 | IWL_DEBUG_RATE(priv, | 827 | IWL_DEBUG_RATE(priv, |
@@ -787,29 +833,31 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
787 | IWL_DEBUG_RATE(priv, | 833 | IWL_DEBUG_RATE(priv, |
788 | "decrease rate because of low tpt\n"); | 834 | "decrease rate because of low tpt\n"); |
789 | scale_action = -1; | 835 | scale_action = -1; |
790 | } else | 836 | } else if (window->success_counter >= IWL_RATE_INCREASE_TH) { |
837 | /* Lower rate has better | ||
838 | * throughput,decrease rate */ | ||
791 | scale_action = 1; | 839 | scale_action = 1; |
840 | } | ||
792 | } | 841 | } |
793 | } | 842 | } |
794 | 843 | ||
795 | if (scale_action == -1) { | 844 | /* Sanity check; asked for decrease, but success rate or throughput |
796 | if (window->success_ratio > IWL_SUCCESS_DOWN_TH) | 845 | * has been good at old rate. Don't change it. */ |
797 | scale_action = 0; | 846 | if ((scale_action == -1) && (low != IWL_RATE_INVALID) && |
798 | } else if (scale_action == 1) { | 847 | ((window->success_ratio > IWL_RATE_HIGH_TH) || |
799 | if (window->success_ratio < IWL_SUCCESS_UP_TH) { | 848 | (current_tpt > (100 * rs_sta->expected_tpt[low])))) |
800 | IWL_DEBUG_RATE(priv, "No action -- success_ratio [%d] < " | 849 | scale_action = 0; |
801 | "SUCCESS UP\n", window->success_ratio); | ||
802 | scale_action = 0; | ||
803 | } | ||
804 | } | ||
805 | 850 | ||
806 | switch (scale_action) { | 851 | switch (scale_action) { |
807 | case -1: | 852 | case -1: |
853 | |||
854 | /* Decrese rate */ | ||
808 | if (low != IWL_RATE_INVALID) | 855 | if (low != IWL_RATE_INVALID) |
809 | index = low; | 856 | index = low; |
810 | break; | 857 | break; |
811 | 858 | ||
812 | case 1: | 859 | case 1: |
860 | /* Increase rate */ | ||
813 | if (high != IWL_RATE_INVALID) | 861 | if (high != IWL_RATE_INVALID) |
814 | index = high; | 862 | index = high; |
815 | 863 | ||
@@ -817,6 +865,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
817 | 865 | ||
818 | case 0: | 866 | case 0: |
819 | default: | 867 | default: |
868 | /* No change */ | ||
820 | break; | 869 | break; |
821 | } | 870 | } |
822 | 871 | ||