* published by the Free Software Foundation.
*/
-#include <linux/module.h>
+#include <linux/jiffies.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/compiler.h>
+#include <linux/module.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
/* This is a minimal implementation of TX rate controlling that can be used
* as the default when no improved mechanisms are available. */
+#define RATE_CONTROL_NUM_DOWN 20
+#define RATE_CONTROL_NUM_UP 15
#define RATE_CONTROL_EMERG_DEC 2
#define RATE_CONTROL_INTERVAL (HZ / 20)
#define RATE_CONTROL_MIN_TX 10
-MODULE_ALIAS("rc80211_default");
-
static void rate_control_rate_inc(struct ieee80211_local *local,
struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_hw_mode *mode;
- int i = sta->txrate;
+ struct ieee80211_supported_band *sband;
+ int i = sta->txrate_idx;
int maxrate;
sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
return;
}
- mode = local->oper_hw_mode;
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
- if (i > mode->num_rates)
- i = mode->num_rates - 2;
+ if (i > sband->n_bitrates)
+ i = sband->n_bitrates - 2;
- while (i + 1 < mode->num_rates) {
+ while (i + 1 < sband->n_bitrates) {
i++;
- if (sta->supp_rates & BIT(i) &&
- mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
+ if (rate_supported(sta, sband->band, i) &&
(maxrate < 0 || i <= maxrate)) {
- sta->txrate = i;
+ sta->txrate_idx = i;
break;
}
}
struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_hw_mode *mode;
- int i = sta->txrate;
+ struct ieee80211_supported_band *sband;
+ int i = sta->txrate_idx;
sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
return;
}
- mode = local->oper_hw_mode;
- if (i > mode->num_rates)
- i = mode->num_rates;
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ if (i > sband->n_bitrates)
+ i = sband->n_bitrates;
while (i > 0) {
i--;
- if (sta->supp_rates & BIT(i) &&
- mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
- sta->txrate = i;
+ if (rate_supported(sta, sband->band, i)) {
+ sta->txrate_idx = i;
break;
}
}
}
-
-static struct ieee80211_rate *
-rate_control_lowest_rate(struct ieee80211_local *local,
- struct ieee80211_hw_mode *mode)
-{
- int i;
-
- for (i = 0; i < mode->num_rates; i++) {
- struct ieee80211_rate *rate = &mode->rates[i];
-
- if (rate->flags & IEEE80211_RATE_SUPPORTED)
- return rate;
- }
-
- printk(KERN_DEBUG "rate_control_lowest_rate - no supported rates "
- "found\n");
- return &mode->rates[0];
-}
-
-
struct global_rate_control {
int dummy;
};
srctrl = sta->rate_ctrl_priv;
srctrl->tx_num_xmit++;
if (status->excessive_retries) {
- sta->antenna_sel_tx = sta->antenna_sel_tx == 1 ? 2 : 1;
- sta->antenna_sel_rx = sta->antenna_sel_rx == 1 ? 2 : 1;
- if (local->sta_antenna_sel == STA_ANTENNA_SEL_SW_CTRL_DEBUG) {
- printk(KERN_DEBUG "%s: " MAC_FMT " TX antenna --> %d "
- "RX antenna --> %d (@%lu)\n",
- dev->name, MAC_ARG(hdr->addr1),
- sta->antenna_sel_tx, sta->antenna_sel_rx, jiffies);
- }
srctrl->tx_num_failures++;
sta->tx_retry_failed++;
sta->tx_num_consecutive_failures++;
}
#endif
- if (per_failed > local->rate_ctrl_num_down) {
+ /*
+ * XXX: Make these configurable once we have an
+ * interface to the rate control algorithms
+ */
+ if (per_failed > RATE_CONTROL_NUM_DOWN) {
rate_control_rate_dec(local, sta);
- } else if (per_failed < local->rate_ctrl_num_up) {
+ } else if (per_failed < RATE_CONTROL_NUM_UP) {
rate_control_rate_inc(local, sta);
}
- srctrl->tx_avg_rate_sum += status->control.rate->rate;
+ srctrl->tx_avg_rate_sum += status->control.tx_rate->bitrate;
srctrl->tx_avg_rate_num++;
srctrl->tx_num_failures = 0;
srctrl->tx_num_xmit = 0;
rate_control_rate_dec(local, sta);
}
- if (srctrl->avg_rate_update + 60 * HZ < jiffies) {
+ if (time_after(jiffies, srctrl->avg_rate_update + 60 * HZ)) {
srctrl->avg_rate_update = jiffies;
if (srctrl->tx_avg_rate_num > 0) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: STA " MAC_FMT " Average rate: "
+ DECLARE_MAC_BUF(mac);
+ printk(KERN_DEBUG "%s: STA %s Average rate: "
"%d (%d/%d)\n",
- dev->name, MAC_ARG(sta->addr),
+ dev->name, print_mac(mac, sta->addr),
srctrl->tx_avg_rate_sum /
srctrl->tx_avg_rate_num,
srctrl->tx_avg_rate_sum,
}
-static struct ieee80211_rate *
+static void
rate_control_simple_get_rate(void *priv, struct net_device *dev,
+ struct ieee80211_supported_band *sband,
struct sk_buff *skb,
- struct rate_control_extra *extra)
+ struct rate_selection *sel)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_hw_mode *mode = extra->mode;
+ struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
- int rateidx, nonerp_idx;
+ int rateidx;
u16 fc;
- memset(extra, 0, sizeof(*extra));
+ sta = sta_info_get(local, hdr->addr1);
+ /* Send management frames and broadcast/multicast data using lowest
+ * rate. */
fc = le16_to_cpu(hdr->frame_control);
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- (hdr->addr1[0] & 0x01)) {
- /* Send management frames and broadcast/multicast data using
- * lowest rate. */
- /* TODO: this could probably be improved.. */
- return rate_control_lowest_rate(local, mode);
+ is_multicast_ether_addr(hdr->addr1) || !sta) {
+ sel->rate = rate_lowest(local, sband, sta);
+ if (sta)
+ sta_info_put(sta);
+ return;
}
- sta = sta_info_get(local, hdr->addr1);
-
- if (!sta)
- return rate_control_lowest_rate(local, mode);
-
+ /* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
- sta->txrate = sdata->bss->force_unicast_rateidx;
+ sta->txrate_idx = sdata->bss->force_unicast_rateidx;
- rateidx = sta->txrate;
+ rateidx = sta->txrate_idx;
- if (rateidx >= mode->num_rates)
- rateidx = mode->num_rates - 1;
+ if (rateidx >= sband->n_bitrates)
+ rateidx = sband->n_bitrates - 1;
- sta->last_txrate = rateidx;
- nonerp_idx = rateidx;
- while (nonerp_idx > 0 &&
- ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
- !(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
- !(sta->supp_rates & BIT(nonerp_idx))))
- nonerp_idx--;
- extra->nonerp = &mode->rates[nonerp_idx];
+ sta->last_txrate_idx = rateidx;
sta_info_put(sta);
- return &mode->rates[rateidx];
+ sel->rate = &sband->bitrates[rateidx];
}
struct ieee80211_local *local,
struct sta_info *sta)
{
- struct ieee80211_hw_mode *mode;
- int i;
- sta->txrate = 0;
- mode = local->oper_hw_mode;
- /* TODO: what is a good starting rate for STA? About middle? Maybe not
- * the lowest or the highest rate.. Could consider using RSSI from
- * previous packets? Need to have IEEE 802.1X auth succeed immediately
- * after assoc.. */
- for (i = 0; i < mode->num_rates; i++) {
- if ((sta->supp_rates & BIT(i)) &&
- (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
- sta->txrate = i;
- }
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ /* TODO: This routine should consider using RSSI from previous packets
+ * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+ * Until that method is implemented, we will use the lowest supported rate
+ * as a workaround, */
+ sta->txrate_idx = rate_lowest_index(local, sband, sta);
}
}
#endif
-static struct rate_control_ops rate_control_simple = {
- .module = THIS_MODULE,
+static struct rate_control_ops mac80211_rcsimple = {
.name = "simple",
.tx_status = rate_control_simple_tx_status,
.get_rate = rate_control_simple_get_rate,
#endif
};
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simple rate control algorithm");
-static int __init rate_control_simple_init(void)
+int __init rc80211_simple_init(void)
{
- return ieee80211_rate_control_register(&rate_control_simple);
+ return ieee80211_rate_control_register(&mac80211_rcsimple);
}
-
-static void __exit rate_control_simple_exit(void)
+void rc80211_simple_exit(void)
{
- ieee80211_rate_control_unregister(&rate_control_simple);
+ ieee80211_rate_control_unregister(&mac80211_rcsimple);
}
-
-module_init(rate_control_simple_init);
-module_exit(rate_control_simple_exit);
-
-MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
-MODULE_LICENSE("GPL");
+#ifdef CONFIG_MAC80211_RC_SIMPLE_MODULE
+module_init(rc80211_simple_init);
+module_exit(rc80211_simple_exit);
+#endif