Fixed AMRR issue with only one Tx antenna and MCS32
[ralink_drivers/rt2860_fbsd8.git] / rt2860_amrr.c
blob84e24bed855e0fd90e9552c3c4cc9ff33cfe47fc
2 /*-
3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com>
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/param.h>
20 #include <sys/kernel.h>
21 #include <sys/module.h>
22 #include <sys/socket.h>
23 #include <sys/sysctl.h>
25 #include <net/if.h>
26 #include <net/if_media.h>
28 #include <net80211/ieee80211_var.h>
30 #include "rt2860_amrr.h"
33 * Defines and macros
36 #define RT2860_AMRR_IS_SUCCESS(amrr_node) ((amrr_node)->retrycnt < (amrr_node)->txcnt / 10)
38 #define RT2860_AMRR_IS_FAILURE(amrr_node) ((amrr_node)->retrycnt > (amrr_node)->txcnt / 3)
40 #define RT2860_AMRR_IS_ENOUGH(amrr_node) ((amrr_node)->txcnt > 10)
43 * Static function prototypes
46 static int rt2860_amrr_update(struct rt2860_amrr *amrr,
47 struct rt2860_amrr_node *amrr_node, struct ieee80211_node *ni);
50 * rt2860_amrr_init
52 void rt2860_amrr_init(struct rt2860_amrr *amrr, struct ieee80211vap *vap,
53 int ntxpath, int min_success_threshold, int max_success_threshold, int msecs)
55 int t;
57 amrr->ntxpath = ntxpath;
59 amrr->min_success_threshold = min_success_threshold;
60 amrr->max_success_threshold = max_success_threshold;
62 if (msecs < 100)
63 msecs = 100;
65 t = msecs_to_ticks(msecs);
67 amrr->interval = (t < 1) ? 1 : t;
71 * rt2860_amrr_cleanup
73 void rt2860_amrr_cleanup(struct rt2860_amrr *amrr)
78 * rt2860_amrr_node_init
80 void rt2860_amrr_node_init(struct rt2860_amrr *amrr,
81 struct rt2860_amrr_node *amrr_node, struct ieee80211_node *ni)
83 const struct ieee80211_rateset *rs;
85 amrr_node->amrr = amrr;
86 amrr_node->success = 0;
87 amrr_node->recovery = 0;
88 amrr_node->txcnt = 0;
89 amrr_node->retrycnt = 0;
90 amrr_node->success_threshold = amrr->min_success_threshold;
92 if (ni->ni_flags & IEEE80211_NODE_HT)
94 rs = (const struct ieee80211_rateset *) &ni->ni_htrates;
96 for (amrr_node->rate_index = rs->rs_nrates - 1;
97 amrr_node->rate_index > 0 && rs->rs_rates[amrr_node->rate_index] > 4;
98 amrr_node->rate_index--) ;
100 ni->ni_txrate = rs->rs_rates[amrr_node->rate_index] | IEEE80211_RATE_MCS;
102 else
104 rs = &ni->ni_rates;
106 for (amrr_node->rate_index = rs->rs_nrates - 1;
107 amrr_node->rate_index > 0 && (rs->rs_rates[amrr_node->rate_index] & IEEE80211_RATE_VAL) > 72;
108 amrr_node->rate_index--) ;
110 ni->ni_txrate = rs->rs_rates[amrr_node->rate_index] & IEEE80211_RATE_VAL;
113 amrr_node->ticks = ticks;
117 * rt2860_amrr_choose
119 int rt2860_amrr_choose(struct ieee80211_node *ni,
120 struct rt2860_amrr_node *amrr_node)
122 struct rt2860_amrr *amrr;
123 int rate_index;
125 amrr = amrr_node->amrr;
127 if (RT2860_AMRR_IS_ENOUGH(amrr_node) &&
128 (ticks - amrr_node->ticks) > amrr->interval)
130 rate_index = rt2860_amrr_update(amrr, amrr_node, ni);
131 if (rate_index != amrr_node->rate_index)
133 if (ni->ni_flags & IEEE80211_NODE_HT)
134 ni->ni_txrate = ni->ni_htrates.rs_rates[rate_index] | IEEE80211_RATE_MCS;
135 else
136 ni->ni_txrate = ni->ni_rates.rs_rates[rate_index] & IEEE80211_RATE_VAL;
138 amrr_node->rate_index = rate_index;
141 amrr_node->ticks = ticks;
143 else
145 rate_index = amrr_node->rate_index;
148 return rate_index;
152 * rt2860_amrr_update
154 static int rt2860_amrr_update(struct rt2860_amrr *amrr,
155 struct rt2860_amrr_node *amrr_node, struct ieee80211_node *ni)
157 const struct ieee80211_rateset *rs;
158 int rate_index;
160 KASSERT(RT2860_AMRR_IS_ENOUGH(amrr_node),
161 ("not enough Tx count: txcnt=%d",
162 amrr_node->txcnt));
164 if (ni->ni_flags & IEEE80211_NODE_HT)
165 rs = (const struct ieee80211_rateset *) &ni->ni_htrates;
166 else
167 rs = &ni->ni_rates;
169 rate_index = amrr_node->rate_index;
171 if (RT2860_AMRR_IS_SUCCESS(amrr_node))
173 amrr_node->success++;
174 if ((amrr_node->success >= amrr_node->success_threshold) &&
175 (rate_index + 1 < rs->rs_nrates) &&
176 (!(ni->ni_flags & IEEE80211_NODE_HT) || rs->rs_rates[rate_index + 1] < (amrr->ntxpath * 8)))
178 amrr_node->recovery = 1;
179 amrr_node->success = 0;
181 rate_index++;
183 else
185 amrr_node->recovery = 0;
188 else if (RT2860_AMRR_IS_FAILURE(amrr_node))
190 amrr_node->success = 0;
192 if (rate_index > 0)
194 if (amrr_node->recovery)
196 amrr_node->success_threshold *= 2;
197 if (amrr_node->success_threshold > amrr->max_success_threshold)
198 amrr_node->success_threshold = amrr->max_success_threshold;
200 else
202 amrr_node->success_threshold = amrr->min_success_threshold;
205 rate_index--;
208 amrr_node->recovery = 0;
211 amrr_node->txcnt = 0;
212 amrr_node->retrycnt = 0;
214 return rate_index;