aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorAbhijeet Kolekar <abhijeet.kolekar@intel.com>2009-03-11 14:17:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-16 18:09:46 -0400
commitdd5b687edacab6cfacf7b9983e86a60c0612e994 (patch)
tree9c6458bfe9e40666d5ca5e69b38496dae14b565c /drivers/net/wireless
parent5c8df2d56a160a31386ee7807adfc1c74e826535 (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.c127
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
131static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) 132static 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