aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_rate.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211_rate.c')
-rw-r--r--net/mac80211/ieee80211_rate.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
index c3f278393741..e495b0998b4d 100644
--- a/net/mac80211/ieee80211_rate.c
+++ b/net/mac80211/ieee80211_rate.c
@@ -147,6 +147,53 @@ static void rate_control_release(struct kref *kref)
147 kfree(ctrl_ref); 147 kfree(ctrl_ref);
148} 148}
149 149
150void rate_control_get_rate(struct net_device *dev,
151 struct ieee80211_hw_mode *mode, struct sk_buff *skb,
152 struct rate_selection *sel)
153{
154 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
155 struct rate_control_ref *ref = local->rate_ctrl;
156 struct ieee80211_sub_if_data *sdata;
157 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
158 struct sta_info *sta = sta_info_get(local, hdr->addr1);
159 int i;
160 u16 fc;
161
162 memset(sel, 0, sizeof(struct rate_selection));
163
164 /* Send management frames and broadcast/multicast data using lowest
165 * rate. */
166 fc = le16_to_cpu(hdr->frame_control);
167 if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
168 is_multicast_ether_addr(hdr->addr1))
169 sel->rate = rate_lowest(local, mode, sta);
170
171 /* If a forced rate is in effect, select it. */
172 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
173 if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
174 sel->rate = &mode->rates[sdata->bss->force_unicast_rateidx];
175
176 /* If we haven't found the rate yet, ask the rate control algo. */
177 if (!sel->rate)
178 ref->ops->get_rate(ref->priv, dev, mode, skb, sel);
179
180 /* Select a non-ERP backup rate. */
181 if (!sel->nonerp) {
182 for (i = 0; i < mode->num_rates - 1; i++) {
183 struct ieee80211_rate *rate = &mode->rates[i];
184 if (sel->rate->rate < rate->rate)
185 break;
186
187 if (rate_supported(sta, mode, i) &&
188 !(rate->flags & IEEE80211_RATE_ERP))
189 sel->nonerp = rate;
190 }
191 }
192
193 if (sta)
194 sta_info_put(sta);
195}
196
150struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) 197struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
151{ 198{
152 kref_get(&ref->kref); 199 kref_get(&ref->kref);