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>
26 #include <net/if_media.h>
28 #include <net80211/ieee80211_var.h>
30 #include "rt2860_amrr.h"
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
);
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
)
57 amrr
->ntxpath
= ntxpath
;
59 amrr
->min_success_threshold
= min_success_threshold
;
60 amrr
->max_success_threshold
= max_success_threshold
;
65 t
= msecs_to_ticks(msecs
);
67 amrr
->interval
= (t
< 1) ? 1 : t
;
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;
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
] & IEEE80211_RATE_VAL
) > 4;
98 amrr_node
->rate_index
--) ;
100 ni
->ni_txrate
= rs
->rs_rates
[amrr_node
->rate_index
] | IEEE80211_RATE_MCS
;
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
;
119 int rt2860_amrr_choose(struct ieee80211_node
*ni
,
120 struct rt2860_amrr_node
*amrr_node
)
122 struct rt2860_amrr
*amrr
;
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
;
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
;
145 rate_index
= amrr_node
->rate_index
;
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
;
160 KASSERT(RT2860_AMRR_IS_ENOUGH(amrr_node
),
161 ("not enough Tx count: txcnt=%d",
164 if (ni
->ni_flags
& IEEE80211_NODE_HT
)
165 rs
= (const struct ieee80211_rateset
*) &ni
->ni_htrates
;
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] & IEEE80211_RATE_VAL
) < (amrr
->ntxpath
* 8)))
178 amrr_node
->recovery
= 1;
179 amrr_node
->success
= 0;
185 amrr_node
->recovery
= 0;
188 else if (RT2860_AMRR_IS_FAILURE(amrr_node
))
190 amrr_node
->success
= 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
;
202 amrr_node
->success_threshold
= amrr
->min_success_threshold
;
208 amrr_node
->recovery
= 0;
211 amrr_node
->txcnt
= 0;
212 amrr_node
->retrycnt
= 0;