summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 23:49:40 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 23:49:40 +0300
commit0191b625ca5a46206d2fb862bb08f36f2fcb3b31 (patch)
tree454d1842b1833d976da62abcbd5c47521ebe9bd7 /drivers/net/wireless/iwlwifi/iwl-3945-rs.c
parent54a696bd07c14d3b1192d03ce7269bc59b45209a (diff)
parenteb56092fc168bf5af199d47af50c0d84a96db898 (diff)
downloadlinux-0191b625ca5a46206d2fb862bb08f36f2fcb3b31.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1429 commits) net: Allow dependancies of FDDI & Tokenring to be modular. igb: Fix build warning when DCA is disabled. net: Fix warning fallout from recent NAPI interface changes. gro: Fix potential use after free sfc: If AN is enabled, always read speed/duplex from the AN advertising bits sfc: When disabling the NIC, close the device rather than unregistering it sfc: SFT9001: Add cable diagnostics sfc: Add support for multiple PHY self-tests sfc: Merge top-level functions for self-tests sfc: Clean up PHY mode management in loopback self-test sfc: Fix unreliable link detection in some loopback modes sfc: Generate unique names for per-NIC workqueues 802.3ad: use standard ethhdr instead of ad_header 802.3ad: generalize out mac address initializer 802.3ad: initialize ports LACPDU from const initializer 802.3ad: remove typedef around ad_system 802.3ad: turn ports is_individual into a bool 802.3ad: turn ports is_enabled into a bool 802.3ad: make ntt bool ixgbe: Fix set_ringparam in ixgbe to use the same memory pools. ... Fixed trivial IPv4/6 address printing conflicts in fs/cifs/connect.c due to the conversion to %pI (in this networking merge) and the addition of doing IPv6 addresses (from the earlier merge of CIFS).
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945-rs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c223
1 files changed, 138 insertions, 85 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 6fc5e7361f26..9b60a0c5de5f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -63,6 +63,9 @@ struct iwl3945_rs_sta {
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
+#ifdef CONFIG_MAC80211_DEBUGFS
+ struct dentry *rs_sta_dbgfs_stats_table_file;
+#endif
/* used to be in sta_info */
int last_txrate_idx;
@@ -114,9 +117,11 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
};
#define IWL_RATE_MAX_WINDOW 62
-#define IWL_RATE_FLUSH (3*HZ/10)
+#define IWL_RATE_FLUSH (3*HZ)
#define IWL_RATE_WIN_FLUSH (HZ/2)
#define IWL_RATE_HIGH_TH 11520
+#define IWL_SUCCESS_UP_TH 8960
+#define IWL_SUCCESS_DOWN_TH 10880
#define IWL_RATE_MIN_FAILURE_TH 8
#define IWL_RATE_MIN_SUCCESS_TH 8
#define IWL_RATE_DECREASE_TH 1920
@@ -203,6 +208,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
#define IWL_RATE_FLUSH_MAX 5000 /* msec */
#define IWL_RATE_FLUSH_MIN 50 /* msec */
+#define IWL_AVERAGE_PACKETS 1500
static void iwl3945_bg_rate_scale_flush(unsigned long data)
{
@@ -217,8 +223,6 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
spin_lock_irqsave(&rs_sta->lock, flags);
- rs_sta->flush_pending = 0;
-
/* Number of packets Rx'd since last time this timer ran */
packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
@@ -227,7 +231,6 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
if (unflushed) {
duration =
jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
-/* duration = jiffies_to_msecs(rs_sta->flush_time); */
IWL_DEBUG_RATE("Tx'd %d packets in %dms\n",
packet_count, duration);
@@ -239,9 +242,11 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
pps = 0;
if (pps) {
- duration = IWL_RATE_FLUSH_MAX / pps;
+ duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
if (duration < IWL_RATE_FLUSH_MIN)
duration = IWL_RATE_FLUSH_MIN;
+ else if (duration > IWL_RATE_FLUSH_MAX)
+ duration = IWL_RATE_FLUSH_MAX;
} else
duration = IWL_RATE_FLUSH_MAX;
@@ -254,8 +259,10 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
rs_sta->flush_time);
rs_sta->last_partial_flush = jiffies;
+ } else {
+ rs_sta->flush_time = IWL_RATE_FLUSH;
+ rs_sta->flush_pending = 0;
}
-
/* If there weren't any unflushed entries, we don't schedule the timer
* to run again */
@@ -275,17 +282,18 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
*/
static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
struct iwl3945_rate_scale_data *window,
- int success, int retries)
+ int success, int retries, int index)
{
unsigned long flags;
+ s32 fail_count;
if (!retries) {
IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n");
return;
}
+ spin_lock_irqsave(&rs_sta->lock, flags);
while (retries--) {
- spin_lock_irqsave(&rs_sta->lock, flags);
/* If we have filled up the window then subtract one from the
* success counter if the high-bit is counting toward
@@ -313,14 +321,25 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
/* Tag this window as having been updated */
window->stamp = jiffies;
- spin_unlock_irqrestore(&rs_sta->lock, flags);
}
+
+ fail_count = window->counter - window->success_counter;
+ if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
+ (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
+ window->average_tpt = ((window->success_ratio *
+ rs_sta->expected_tpt[index] + 64) / 128);
+ else
+ window->average_tpt = IWL_INV_TPT;
+
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
+
}
-static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
+static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct iwl3945_rs_sta *rs_sta = priv_sta;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
int i;
IWL_DEBUG_RATE("enter\n");
@@ -330,16 +349,21 @@ static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
* previous packets? Need to have IEEE 802.1X auth succeed immediately
* after assoc.. */
- for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
+ for (i = sband->n_bitrates - 1; i >= 0; i--) {
if (sta->supp_rates[sband->band] & (1 << i)) {
rs_sta->last_txrate_idx = i;
break;
}
}
+ priv->sta_supp_rates = sta->supp_rates[sband->band];
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
- if (sband->band == IEEE80211_BAND_5GHZ)
+ if (sband->band == IEEE80211_BAND_5GHZ) {
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+ priv->sta_supp_rates = priv->sta_supp_rates <<
+ IWL_FIRST_OFDM_RATE;
+ }
+
IWL_DEBUG_RATE("leave\n");
}
@@ -355,12 +379,6 @@ static void rs_free(void *priv)
return;
}
-static void rs_clear(void *priv)
-{
- return;
-}
-
-
static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct iwl3945_rs_sta *rs_sta;
@@ -422,34 +440,6 @@ static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
}
-/*
- * get ieee prev rate from rate scale table.
- * for A and B mode we need to overright prev
- * value
- */
-static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
-{
- int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
- switch (priv->band) {
- case IEEE80211_BAND_5GHZ:
- if (rate == IWL_RATE_12M_INDEX)
- next_rate = IWL_RATE_9M_INDEX;
- else if (rate == IWL_RATE_6M_INDEX)
- next_rate = IWL_RATE_6M_INDEX;
- break;
-/* XXX cannot be invoked in current mac80211 so not a regression
- case MODE_IEEE80211B:
- if (rate == IWL_RATE_11M_INDEX_TABLE)
- next_rate = IWL_RATE_5M_INDEX_TABLE;
- break;
- */
- default:
- break;
- }
-
- return next_rate;
-}
/**
* rs_tx_status - Update rate control values based on Tx results
*
@@ -460,7 +450,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
- u8 retries, current_count;
+ s8 retries = 0, current_count;
int scale_rate_index, first_index, last_index;
unsigned long flags;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
@@ -469,8 +459,9 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
IWL_DEBUG_RATE("enter\n");
- retries = info->status.retry_count;
- first_index = sband->bitrates[info->tx_rate_idx].hw_value;
+ retries = info->status.rates[0].count;
+
+ first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
return;
@@ -496,13 +487,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
* at which the frame was finally transmitted (or failed if no
* ACK)
*/
- while (retries > 0) {
- if (retries < priv->retry_rate) {
- current_count = retries;
+ while (retries > 1) {
+ if ((retries - 1) < priv->retry_rate) {
+ current_count = (retries - 1);
last_index = scale_rate_index;
} else {
current_count = priv->retry_rate;
- last_index = rs_adjust_next_rate(priv,
+ last_index = iwl3945_rs_next_rate(priv,
scale_rate_index);
}
@@ -510,15 +501,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
* as was used for it (per current_count) */
iwl3945_collect_tx_data(rs_sta,
&rs_sta->win[scale_rate_index],
- 0, current_count);
+ 0, current_count, scale_rate_index);
IWL_DEBUG_RATE("Update rate %d for %d retries.\n",
scale_rate_index, current_count);
retries -= current_count;
- if (retries)
- scale_rate_index =
- rs_adjust_next_rate(priv, scale_rate_index);
+ scale_rate_index = last_index;
}
@@ -529,7 +518,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
"success" : "failure");
iwl3945_collect_tx_data(rs_sta,
&rs_sta->win[last_index],
- info->flags & IEEE80211_TX_STAT_ACK, 1);
+ info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
/* We updated the rate scale window -- if its been more than
* flush_time since the last run, schedule the flush
@@ -537,9 +526,10 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
spin_lock_irqsave(&rs_sta->lock, flags);
if (!rs_sta->flush_pending &&
- time_after(jiffies, rs_sta->last_partial_flush +
+ time_after(jiffies, rs_sta->last_flush +
rs_sta->flush_time)) {
+ rs_sta->last_partial_flush = jiffies;
rs_sta->flush_pending = 1;
mod_timer(&rs_sta->rate_scale_flush,
jiffies + rs_sta->flush_time);
@@ -630,10 +620,11 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
* rate table and must reference the driver allocated rate table
*
*/
-static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- struct sk_buff *skb, struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
+ void *priv_sta, struct ieee80211_tx_rate_control *txrc)
{
+ struct ieee80211_supported_band *sband = txrc->sband;
+ struct sk_buff *skb = txrc->skb;
u8 low = IWL_RATE_INVALID;
u8 high = IWL_RATE_INVALID;
u16 high_low;
@@ -649,7 +640,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
u16 fc, rate_mask;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
- DECLARE_MAC_BUF(mac);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n");
@@ -660,7 +651,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- sel->rate_idx = rate_lowest_index(sband, sta);
+ info->control.rates[0].idx = rate_lowest_index(sband, sta);
return;
}
@@ -675,8 +666,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_RATE("LQ: ADD station %s\n",
- print_mac(mac, hdr->addr1));
+ IWL_DEBUG_RATE("LQ: ADD station %pm\n",
+ hdr->addr1);
sta_id = iwl3945_add_station(priv,
hdr->addr1, 0, CMD_ASYNC);
}
@@ -686,8 +677,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
spin_lock_irqsave(&rs_sta->lock, flags);
+ /* for recent assoc, choose best rate regarding
+ * to rssi value
+ */
if (rs_sta->start_rate != IWL_RATE_INVALID) {
- index = rs_sta->start_rate;
+ if (rs_sta->start_rate < index &&
+ (rate_mask & (1 << rs_sta->start_rate)))
+ index = rs_sta->start_rate;
rs_sta->start_rate = IWL_RATE_INVALID;
}
@@ -697,7 +693,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
- window->average_tpt = IWL_INV_TPT;
spin_unlock_irqrestore(&rs_sta->lock, flags);
IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
@@ -711,8 +706,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
}
- window->average_tpt = ((window->success_ratio *
- rs_sta->expected_tpt[index] + 64) / 128);
current_tpt = window->average_tpt;
high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
@@ -760,13 +753,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
}
}
- if ((window->success_ratio > IWL_RATE_HIGH_TH) ||
- (current_tpt > window->average_tpt)) {
- IWL_DEBUG_RATE("No action -- success_ratio [%d] > HIGH_TH or "
- "current_tpt [%d] > average_tpt [%d]\n",
- window->success_ratio,
- current_tpt, window->average_tpt);
- scale_action = 0;
+ if (scale_action == -1) {
+ if (window->success_ratio > IWL_SUCCESS_DOWN_TH)
+ scale_action = 0;
+ } else if (scale_action == 1) {
+ if (window->success_ratio < IWL_SUCCESS_UP_TH) {
+ IWL_DEBUG_RATE("No action -- success_ratio [%d] < "
+ "SUCCESS UP\n", window->success_ratio);
+ scale_action = 0;
+ }
}
switch (scale_action) {
@@ -793,24 +788,83 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
rs_sta->last_txrate_idx = index;
if (sband->band == IEEE80211_BAND_5GHZ)
- sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
+ info->control.rates[0].idx = rs_sta->last_txrate_idx -
+ IWL_FIRST_OFDM_RATE;
else
- sel->rate_idx = rs_sta->last_txrate_idx;
+ info->control.rates[0].idx = rs_sta->last_txrate_idx;
IWL_DEBUG_RATE("leave: %d\n", index);
}
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buff[1024];
+ int desc = 0;
+ int j;
+ struct iwl3945_rs_sta *lq_sta = file->private_data;
+
+ desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
+ "rate=0x%X flush time %d\n",
+ lq_sta->tx_packets,
+ lq_sta->last_txrate_idx,
+ lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
+ for (j = 0; j < IWL_RATE_COUNT; j++) {
+ desc += sprintf(buff+desc,
+ "counter=%d success=%d %%=%d\n",
+ lq_sta->win[j].counter,
+ lq_sta->win[j].success_counter,
+ lq_sta->win[j].success_ratio);
+ }
+ return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+ .read = iwl3945_sta_dbgfs_stats_table_read,
+ .open = iwl3945_open_file_generic,
+};
+
+static void iwl3945_add_debugfs(void *priv, void *priv_sta,
+ struct dentry *dir)
+{
+ struct iwl3945_rs_sta *lq_sta = priv_sta;
+
+ lq_sta->rs_sta_dbgfs_stats_table_file =
+ debugfs_create_file("rate_stats_table", 0600, dir,
+ lq_sta, &rs_sta_dbgfs_stats_table_ops);
+
+}
+
+static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
+{
+ struct iwl3945_rs_sta *lq_sta = priv_sta;
+ debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+}
+#endif
+
static struct rate_control_ops rs_ops = {
.module = NULL,
.name = RS_NAME,
.tx_status = rs_tx_status,
.get_rate = rs_get_rate,
.rate_init = rs_rate_init,
- .clear = rs_clear,
.alloc = rs_alloc,
.free = rs_free,
.alloc_sta = rs_alloc_sta,
.free_sta = rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+ .add_sta_debugfs = iwl3945_add_debugfs,
+ .remove_sta_debugfs = iwl3945_remove_debugfs,
+#endif
+
};
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
@@ -827,13 +881,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rcu_read_lock();
sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
- psta = (void *) sta->drv_priv;
- if (!sta || !psta) {
- IWL_DEBUG_RATE("leave - no private rate data!\n");
+ if (!sta) {
rcu_read_unlock();
return;
}
+ psta = (void *) sta->drv_priv;
rs_sta = psta->rs_sta;
spin_lock_irqsave(&rs_sta->lock, flags);
@@ -857,7 +910,6 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
break;
}
- rcu_read_unlock();
spin_unlock_irqrestore(&rs_sta->lock, flags);
rssi = priv->last_rx_rssi;
@@ -871,6 +923,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
"%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
iwl3945_rates[rs_sta->start_rate].plcp);
+ rcu_read_unlock();
}
int iwl3945_rate_control_register(void)