iwl-3945-rs.c 24.1 KB
Newer Older
Z
Zhu Yi 已提交
1 2
/******************************************************************************
 *
R
Reinette Chatre 已提交
3
 * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
Z
Zhu Yi 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
22
 *  Intel Linux Wireless <ilw@linux.intel.com>
Z
Zhu Yi 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/wireless.h>
#include <net/mac80211.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>

#include <linux/workqueue.h>

39
#include "iwl-3945.h"
Z
Zhu Yi 已提交
40 41 42

#define RS_NAME "iwl-3945-rs"

C
Christoph Hellwig 已提交
43
struct iwl3945_rate_scale_data {
Z
Zhu Yi 已提交
44 45 46 47 48 49 50 51
	u64 data;
	s32 success_counter;
	s32 success_ratio;
	s32 counter;
	s32 average_tpt;
	unsigned long stamp;
};

52
struct iwl3945_rs_sta {
Z
Zhu Yi 已提交
53 54 55 56 57 58 59 60 61 62 63 64
	spinlock_t lock;
	s32 *expected_tpt;
	unsigned long last_partial_flush;
	unsigned long last_flush;
	u32 flush_time;
	u32 last_tx_packets;
	u32 tx_packets;
	u8 tgg;
	u8 flush_pending;
	u8 start_rate;
	u8 ibss_sta_added;
	struct timer_list rate_scale_flush;
C
Christoph Hellwig 已提交
65
	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
A
Abbas, Mohamed 已提交
66 67 68
#ifdef CONFIG_MAC80211_DEBUGFS
	struct dentry *rs_sta_dbgfs_stats_table_file;
#endif
69 70 71

	/* used to be in sta_info */
	int last_txrate_idx;
Z
Zhu Yi 已提交
72 73
};

C
Christoph Hellwig 已提交
74
static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = {
75
	7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
Z
Zhu Yi 已提交
76 77
};

C
Christoph Hellwig 已提交
78
static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT] = {
79
	7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
Z
Zhu Yi 已提交
80 81
};

C
Christoph Hellwig 已提交
82
static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT] = {
83
	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
Z
Zhu Yi 已提交
84 85
};

C
Christoph Hellwig 已提交
86
static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT] = {
87
	7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
Z
Zhu Yi 已提交
88 89
};

C
Christoph Hellwig 已提交
90
struct iwl3945_tpt_entry {
Z
Zhu Yi 已提交
91 92 93 94
	s8 min_rssi;
	u8 index;
};

C
Christoph Hellwig 已提交
95
static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
Z
Zhu Yi 已提交
96 97 98 99 100 101 102 103 104 105
	{-60, IWL_RATE_54M_INDEX},
	{-64, IWL_RATE_48M_INDEX},
	{-72, IWL_RATE_36M_INDEX},
	{-80, IWL_RATE_24M_INDEX},
	{-84, IWL_RATE_18M_INDEX},
	{-85, IWL_RATE_12M_INDEX},
	{-87, IWL_RATE_9M_INDEX},
	{-89, IWL_RATE_6M_INDEX}
};

C
Christoph Hellwig 已提交
106
static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
Z
Zhu Yi 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119
	{-60, IWL_RATE_54M_INDEX},
	{-64, IWL_RATE_48M_INDEX},
	{-68, IWL_RATE_36M_INDEX},
	{-80, IWL_RATE_24M_INDEX},
	{-84, IWL_RATE_18M_INDEX},
	{-85, IWL_RATE_12M_INDEX},
	{-86, IWL_RATE_11M_INDEX},
	{-88, IWL_RATE_5M_INDEX},
	{-90, IWL_RATE_2M_INDEX},
	{-92, IWL_RATE_1M_INDEX}
};

#define IWL_RATE_MAX_WINDOW          62
120
#define IWL_RATE_FLUSH       	 (3*HZ)
Z
Zhu Yi 已提交
121 122
#define IWL_RATE_WIN_FLUSH       (HZ/2)
#define IWL_RATE_HIGH_TH          11520
123 124
#define IWL_SUCCESS_UP_TH	   8960
#define IWL_SUCCESS_DOWN_TH	  10880
Z
Zhu Yi 已提交
125 126 127 128
#define IWL_RATE_MIN_FAILURE_TH       8
#define IWL_RATE_MIN_SUCCESS_TH       8
#define IWL_RATE_DECREASE_TH       1920

129
static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
Z
Zhu Yi 已提交
130 131 132
{
	u32 index = 0;
	u32 table_size = 0;
C
Christoph Hellwig 已提交
133
	struct iwl3945_tpt_entry *tpt_table = NULL;
Z
Zhu Yi 已提交
134 135 136 137

	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
		rssi = IWL_MIN_RSSI_VAL;

138 139
	switch (band) {
	case IEEE80211_BAND_2GHZ:
C
Christoph Hellwig 已提交
140 141
		tpt_table = iwl3945_tpt_table_g;
		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
Z
Zhu Yi 已提交
142 143
		break;

144
	case IEEE80211_BAND_5GHZ:
C
Christoph Hellwig 已提交
145 146
		tpt_table = iwl3945_tpt_table_a;
		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
Z
Zhu Yi 已提交
147 148 149
		break;

	default:
150
		BUG();
Z
Zhu Yi 已提交
151 152 153 154 155 156 157 158 159 160 161
		break;
	}

	while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
		index++;

	index = min(index, (table_size - 1));

	return tpt_table[index].index;
}

C
Christoph Hellwig 已提交
162
static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
Z
Zhu Yi 已提交
163 164 165
{
	window->data = 0;
	window->success_counter = 0;
T
Tomas Winkler 已提交
166
	window->success_ratio = -1;
Z
Zhu Yi 已提交
167
	window->counter = 0;
T
Tomas Winkler 已提交
168
	window->average_tpt = IWL_INV_TPT;
Z
Zhu Yi 已提交
169 170 171 172
	window->stamp = 0;
}

/**
C
Christoph Hellwig 已提交
173
 * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
Z
Zhu Yi 已提交
174 175 176 177 178
 *
 * Returns the number of windows that have gathered data but were
 * not flushed.  If there were any that were not flushed, then
 * reschedule the rate flushing routine.
 */
179
static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
Z
Zhu Yi 已提交
180 181 182 183 184 185 186 187 188 189 190
{
	int unflushed = 0;
	int i;
	unsigned long flags;

	/*
	 * For each rate, if we have collected data on that rate
	 * and it has been more than IWL_RATE_WIN_FLUSH
	 * since we flushed, clear out the gathered statistics
	 */
	for (i = 0; i < IWL_RATE_COUNT; i++) {
191
		if (!rs_sta->win[i].counter)
Z
Zhu Yi 已提交
192 193
			continue;

194 195
		spin_lock_irqsave(&rs_sta->lock, flags);
		if (time_after(jiffies, rs_sta->win[i].stamp +
Z
Zhu Yi 已提交
196 197 198
			       IWL_RATE_WIN_FLUSH)) {
			IWL_DEBUG_RATE("flushing %d samples of rate "
				       "index %d\n",
199 200
				       rs_sta->win[i].counter, i);
			iwl3945_clear_window(&rs_sta->win[i]);
Z
Zhu Yi 已提交
201 202
		} else
			unflushed++;
203
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
204 205 206 207 208 209 210
	}

	return unflushed;
}

#define IWL_RATE_FLUSH_MAX              5000	/* msec */
#define IWL_RATE_FLUSH_MIN              50	/* msec */
211
#define IWL_AVERAGE_PACKETS             1500
Z
Zhu Yi 已提交
212

C
Christoph Hellwig 已提交
213
static void iwl3945_bg_rate_scale_flush(unsigned long data)
Z
Zhu Yi 已提交
214
{
215
	struct iwl3945_rs_sta *rs_sta = (void *)data;
Z
Zhu Yi 已提交
216 217 218 219 220 221
	int unflushed = 0;
	unsigned long flags;
	u32 packet_count, duration, pps;

	IWL_DEBUG_RATE("enter\n");

222
	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
Z
Zhu Yi 已提交
223

224
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
225 226

	/* Number of packets Rx'd since last time this timer ran */
227
	packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
Z
Zhu Yi 已提交
228

229
	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
Z
Zhu Yi 已提交
230 231 232

	if (unflushed) {
		duration =
233
		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
Z
Zhu Yi 已提交
234 235 236 237 238 239 240 241 242 243 244

		IWL_DEBUG_RATE("Tx'd %d packets in %dms\n",
			       packet_count, duration);

		/* Determine packets per second */
		if (duration)
			pps = (packet_count * 1000) / duration;
		else
			pps = 0;

		if (pps) {
245
			duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
Z
Zhu Yi 已提交
246 247
			if (duration < IWL_RATE_FLUSH_MIN)
				duration = IWL_RATE_FLUSH_MIN;
248 249
			else if (duration > IWL_RATE_FLUSH_MAX)
				duration = IWL_RATE_FLUSH_MAX;
Z
Zhu Yi 已提交
250 251 252
		} else
			duration = IWL_RATE_FLUSH_MAX;

253
		rs_sta->flush_time = msecs_to_jiffies(duration);
Z
Zhu Yi 已提交
254 255 256 257

		IWL_DEBUG_RATE("new flush period: %d msec ave %d\n",
			       duration, packet_count);

258 259
		mod_timer(&rs_sta->rate_scale_flush, jiffies +
			  rs_sta->flush_time);
Z
Zhu Yi 已提交
260

261
		rs_sta->last_partial_flush = jiffies;
262 263 264
	} else {
		rs_sta->flush_time = IWL_RATE_FLUSH;
		rs_sta->flush_pending = 0;
Z
Zhu Yi 已提交
265 266 267 268
	}
	/* If there weren't any unflushed entries, we don't schedule the timer
	 * to run again */

269
	rs_sta->last_flush = jiffies;
Z
Zhu Yi 已提交
270

271
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
272 273 274 275 276

	IWL_DEBUG_RATE("leave\n");
}

/**
C
Christoph Hellwig 已提交
277
 * iwl3945_collect_tx_data - Update the success/failure sliding window
Z
Zhu Yi 已提交
278 279 280 281 282
 *
 * We keep a sliding window of the last 64 packets transmitted
 * at this rate.  window->data contains the bitmask of successful
 * packets.
 */
283
static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
C
Christoph Hellwig 已提交
284
				struct iwl3945_rate_scale_data *window,
285
				int success, int retries, int index)
Z
Zhu Yi 已提交
286 287
{
	unsigned long flags;
288
	s32 fail_count;
Z
Zhu Yi 已提交
289 290 291 292 293 294

	if (!retries) {
		IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n");
		return;
	}

295
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
	while (retries--) {

		/* If we have filled up the window then subtract one from the
		 * success counter if the high-bit is counting toward
		 * success */
		if (window->counter == IWL_RATE_MAX_WINDOW) {
			if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1)))
				window->success_counter--;
		} else
			window->counter++;

		/* Slide the window to the left one bit */
		window->data = (window->data << 1);

		/* If this packet was a success then set the low bit high */
		if (success) {
			window->success_counter++;
			window->data |= 1;
		}

		/* window->counter can't be 0 -- it is either >0 or
		 * IWL_RATE_MAX_WINDOW */
		window->success_ratio = 12800 * window->success_counter /
		    window->counter;

		/* Tag this window as having been updated */
		window->stamp = jiffies;

	}
325 326 327 328 329 330 331 332 333 334 335

	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);

Z
Zhu Yi 已提交
336 337
}

338
static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
339
			 struct ieee80211_sta *sta, void *priv_sta)
Z
Zhu Yi 已提交
340
{
341
	struct iwl3945_rs_sta *rs_sta = priv_sta;
342
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
Z
Zhu Yi 已提交
343 344 345 346 347 348 349 350 351
	int i;

	IWL_DEBUG_RATE("enter\n");

	/* 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.. */

352
	for (i = sband->n_bitrates - 1; i >= 0; i--) {
353
		if (sta->supp_rates[sband->band] & (1 << i)) {
354
			rs_sta->last_txrate_idx = i;
Z
Zhu Yi 已提交
355 356 357 358
			break;
		}
	}

359
	priv->sta_supp_rates = sta->supp_rates[sband->band];
360
	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
361
	if (sband->band == IEEE80211_BAND_5GHZ) {
362
		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
363 364 365 366
		priv->sta_supp_rates = priv->sta_supp_rates <<
						IWL_FIRST_OFDM_RATE;
	}

367

Z
Zhu Yi 已提交
368 369 370
	IWL_DEBUG_RATE("leave\n");
}

371
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
Z
Zhu Yi 已提交
372
{
373
	return hw->priv;
Z
Zhu Yi 已提交
374 375
}

376
/* rate scale requires free function to be implemented */
Z
Zhu Yi 已提交
377 378 379 380
static void rs_free(void *priv)
{
	return;
}
381 382

static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
Z
Zhu Yi 已提交
383
{
384
	struct iwl3945_rs_sta *rs_sta;
385
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
Z
Zhu Yi 已提交
386 387
	int i;

388 389 390 391 392
	/*
	 * XXX: If it's using sta->drv_priv anyway, it might
	 *	as well just put all the information there.
	 */

Z
Zhu Yi 已提交
393 394
	IWL_DEBUG_RATE("enter\n");

395 396
	rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
	if (!rs_sta) {
Z
Zhu Yi 已提交
397 398 399 400
		IWL_DEBUG_RATE("leave: ENOMEM\n");
		return NULL;
	}

401 402
	psta->rs_sta = rs_sta;

403
	spin_lock_init(&rs_sta->lock);
Z
Zhu Yi 已提交
404

405
	rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
406 407

	/* default to just 802.11b */
408
	rs_sta->expected_tpt = iwl3945_expected_tpt_b;
Z
Zhu Yi 已提交
409

410 411 412 413 414
	rs_sta->last_partial_flush = jiffies;
	rs_sta->last_flush = jiffies;
	rs_sta->flush_time = IWL_RATE_FLUSH;
	rs_sta->last_tx_packets = 0;
	rs_sta->ibss_sta_added = 0;
Z
Zhu Yi 已提交
415

416 417 418
	init_timer(&rs_sta->rate_scale_flush);
	rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
	rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush;
Z
Zhu Yi 已提交
419 420

	for (i = 0; i < IWL_RATE_COUNT; i++)
421
		iwl3945_clear_window(&rs_sta->win[i]);
Z
Zhu Yi 已提交
422 423 424

	IWL_DEBUG_RATE("leave\n");

425
	return rs_sta;
Z
Zhu Yi 已提交
426 427
}

428 429
static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
			void *priv_sta)
Z
Zhu Yi 已提交
430
{
431
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
432
	struct iwl3945_rs_sta *rs_sta = priv_sta;
Z
Zhu Yi 已提交
433

434 435
	psta->rs_sta = NULL;

Z
Zhu Yi 已提交
436
	IWL_DEBUG_RATE("enter\n");
437 438
	del_timer_sync(&rs_sta->rate_scale_flush);
	kfree(rs_sta);
Z
Zhu Yi 已提交
439 440 441
	IWL_DEBUG_RATE("leave\n");
}

442

Z
Zhu Yi 已提交
443 444 445
/**
 * rs_tx_status - Update rate control values based on Tx results
 *
C
Christoph Hellwig 已提交
446
 * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by
Z
Zhu Yi 已提交
447 448
 * the hardware for each rate.
 */
449 450
static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
			 struct ieee80211_sta *sta, void *priv_sta,
451
			 struct sk_buff *skb)
Z
Zhu Yi 已提交
452
{
453
	s8 retries = 0, current_count;
Z
Zhu Yi 已提交
454 455
	int scale_rate_index, first_index, last_index;
	unsigned long flags;
C
Christoph Hellwig 已提交
456
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
457
	struct iwl3945_rs_sta *rs_sta = priv_sta;
458
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
459

T
Tomas Winkler 已提交
460 461
	IWL_DEBUG_RATE("enter\n");

462
	retries = info->status.rates[0].count;
463 464

	first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
Z
Zhu Yi 已提交
465
	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
466
		IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
Z
Zhu Yi 已提交
467 468 469
		return;
	}

470
	if (!priv_sta) {
Z
Zhu Yi 已提交
471 472 473 474
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
		return;
	}

475
	rs_sta->tx_packets++;
Z
Zhu Yi 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489

	scale_rate_index = first_index;
	last_index = first_index;

	/*
	 * Update the window for each rate.  We determine which rates
	 * were Tx'd based on the total number of retries vs. the number
	 * of retries configured for each rate -- currently set to the
	 * priv value 'retry_rate' vs. rate specific
	 *
	 * On exit from this while loop last_index indicates the rate
	 * at which the frame was finally transmitted (or failed if no
	 * ACK)
	 */
490 491 492
	while (retries > 1) {
		if ((retries - 1) < priv->retry_rate) {
			current_count = (retries - 1);
Z
Zhu Yi 已提交
493 494 495
			last_index = scale_rate_index;
		} else {
			current_count = priv->retry_rate;
496
			last_index = iwl3945_rs_next_rate(priv,
497
							 scale_rate_index);
Z
Zhu Yi 已提交
498 499 500 501
		}

		/* Update this rate accounting for as many retries
		 * as was used for it (per current_count) */
502 503
		iwl3945_collect_tx_data(rs_sta,
				    &rs_sta->win[scale_rate_index],
504
				    0, current_count, scale_rate_index);
Z
Zhu Yi 已提交
505 506 507 508 509
		IWL_DEBUG_RATE("Update rate %d for %d retries.\n",
			       scale_rate_index, current_count);

		retries -= current_count;

510
		scale_rate_index = last_index;
Z
Zhu Yi 已提交
511 512
	}

513

Z
Zhu Yi 已提交
514 515 516
	/* Update the last index window with success/failure based on ACK */
	IWL_DEBUG_RATE("Update rate %d with %s.\n",
		       last_index,
517
		       (info->flags & IEEE80211_TX_STAT_ACK) ?
Z
Zhu Yi 已提交
518
		       "success" : "failure");
519 520
	iwl3945_collect_tx_data(rs_sta,
			    &rs_sta->win[last_index],
521
			    info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
Z
Zhu Yi 已提交
522 523 524 525

	/* We updated the rate scale window -- if its been more than
	 * flush_time since the last run, schedule the flush
	 * again */
526
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
527

528
	if (!rs_sta->flush_pending &&
529
	    time_after(jiffies, rs_sta->last_flush +
530
		       rs_sta->flush_time)) {
Z
Zhu Yi 已提交
531

532
		rs_sta->last_partial_flush = jiffies;
533 534 535
		rs_sta->flush_pending = 1;
		mod_timer(&rs_sta->rate_scale_flush,
			  jiffies + rs_sta->flush_time);
Z
Zhu Yi 已提交
536 537
	}

538
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
539 540 541 542 543 544

	IWL_DEBUG_RATE("leave\n");

	return;
}

545
static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
546
				 u8 index, u16 rate_mask, enum ieee80211_band band)
Z
Zhu Yi 已提交
547 548 549 550
{
	u8 high = IWL_RATE_INVALID;
	u8 low = IWL_RATE_INVALID;

551
	/* 802.11A walks to the next literal adjacent rate in
Z
Zhu Yi 已提交
552
	 * the rate table */
553
	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
Z
Zhu Yi 已提交
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
		int i;
		u32 mask;

		/* Find the previous rate that is in the rate mask */
		i = index - 1;
		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
			if (rate_mask & mask) {
				low = i;
				break;
			}
		}

		/* Find the next rate that is in the rate mask */
		i = index + 1;
		for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) {
			if (rate_mask & mask) {
				high = i;
				break;
			}
		}

		return (high << 8) | low;
	}

	low = index;
	while (low != IWL_RATE_INVALID) {
580
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
581
			low = iwl3945_rates[low].prev_rs_tgg;
Z
Zhu Yi 已提交
582
		else
C
Christoph Hellwig 已提交
583
			low = iwl3945_rates[low].prev_rs;
Z
Zhu Yi 已提交
584 585 586 587 588 589 590 591 592
		if (low == IWL_RATE_INVALID)
			break;
		if (rate_mask & (1 << low))
			break;
		IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low);
	}

	high = index;
	while (high != IWL_RATE_INVALID) {
593
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
594
			high = iwl3945_rates[high].next_rs_tgg;
Z
Zhu Yi 已提交
595
		else
C
Christoph Hellwig 已提交
596
			high = iwl3945_rates[high].next_rs;
Z
Zhu Yi 已提交
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
		if (high == IWL_RATE_INVALID)
			break;
		if (rate_mask & (1 << high))
			break;
		IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high);
	}

	return (high << 8) | low;
}

/**
 * rs_get_rate - find the rate for the requested packet
 *
 * Returns the ieee80211_rate structure allocated by the driver.
 *
 * The rate control algorithm has no internal mapping between hw_mode's
 * rate ordering and the rate ordering used by the rate control algorithm.
 *
 * The rate control algorithm uses a single table of rates that goes across
 * the entire A/B/G spectrum vs. being limited to just one particular
 * hw_mode.
 *
 * As such, we can't convert the index obtained below into the hw_mode's
 * rate table and must reference the driver allocated rate table
 *
 */
623 624
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
Z
Zhu Yi 已提交
625
{
626 627
	struct ieee80211_supported_band *sband = txrc->sband;
	struct sk_buff *skb = txrc->skb;
Z
Zhu Yi 已提交
628 629 630 631
	u8 low = IWL_RATE_INVALID;
	u8 high = IWL_RATE_INVALID;
	u16 high_low;
	int index;
632
	struct iwl3945_rs_sta *rs_sta = priv_sta;
C
Christoph Hellwig 已提交
633
	struct iwl3945_rate_scale_data *window = NULL;
T
Tomas Winkler 已提交
634 635 636
	int current_tpt = IWL_INV_TPT;
	int low_tpt = IWL_INV_TPT;
	int high_tpt = IWL_INV_TPT;
Z
Zhu Yi 已提交
637 638 639 640
	u32 fail_count;
	s8 scale_action = 0;
	unsigned long flags;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
641
	u16 fc, rate_mask;
642
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
643
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Z
Zhu Yi 已提交
644 645 646

	IWL_DEBUG_RATE("enter\n");

647 648 649 650 651
	/* 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 ||
	    is_multicast_ether_addr(hdr->addr1) ||
652
	    !sta || !priv_sta) {
Z
Zhu Yi 已提交
653
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
654
		info->control.rates[0].idx = rate_lowest_index(sband, sta);
655
		return;
Z
Zhu Yi 已提交
656 657
	}

658
	rate_mask = sta->supp_rates[sband->band];
659
	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
660

T
Tomas Winkler 已提交
661
	if (sband->band == IEEE80211_BAND_5GHZ)
662
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
663

664
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
665
	    !rs_sta->ibss_sta_added) {
C
Christoph Hellwig 已提交
666
		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
667 668

		if (sta_id == IWL_INVALID_STATION) {
J
Johannes Berg 已提交
669 670
			IWL_DEBUG_RATE("LQ: ADD station %pm\n",
				       hdr->addr1);
C
Christoph Hellwig 已提交
671
			sta_id = iwl3945_add_station(priv,
Z
Zhu Yi 已提交
672 673 674
				    hdr->addr1, 0, CMD_ASYNC);
		}
		if (sta_id != IWL_INVALID_STATION)
675
			rs_sta->ibss_sta_added = 1;
Z
Zhu Yi 已提交
676 677
	}

678
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
679

680 681 682
	/* for recent assoc, choose best rate regarding
	 * to rssi value
	 */
683
	if (rs_sta->start_rate != IWL_RATE_INVALID) {
684 685 686
		if (rs_sta->start_rate < index &&
		   (rate_mask & (1 << rs_sta->start_rate)))
			index = rs_sta->start_rate;
687
		rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
688 689
	}

690
	window = &(rs_sta->win[index]);
Z
Zhu Yi 已提交
691 692 693 694 695

	fail_count = window->counter - window->success_counter;

	if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
696
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
697 698 699 700 701 702 703

		IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
			       "counter: %d, success_counter: %d, "
			       "expected_tpt is %sNULL\n",
			       index,
			       window->counter,
			       window->success_counter,
704
			       rs_sta->expected_tpt ? "not " : "");
Z
Zhu Yi 已提交
705 706 707 708 709 710
		goto out;

	}

	current_tpt = window->average_tpt;

711
	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
T
Tomas Winkler 已提交
712
					     sband->band);
Z
Zhu Yi 已提交
713 714 715 716
	low = high_low & 0xff;
	high = (high_low >> 8) & 0xff;

	if (low != IWL_RATE_INVALID)
717
		low_tpt = rs_sta->win[low].average_tpt;
Z
Zhu Yi 已提交
718 719

	if (high != IWL_RATE_INVALID)
720
		high_tpt = rs_sta->win[high].average_tpt;
Z
Zhu Yi 已提交
721

722
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
723 724 725 726 727 728

	scale_action = 1;

	if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
		IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
		scale_action = -1;
T
Tomas Winkler 已提交
729
	} else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
Z
Zhu Yi 已提交
730
		scale_action = 1;
T
Tomas Winkler 已提交
731 732
	else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
Z
Zhu Yi 已提交
733 734 735 736 737
		IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
			       "current_tpt [%d]\n",
			       low_tpt, high_tpt, current_tpt);
		scale_action = 0;
	} else {
T
Tomas Winkler 已提交
738
		if (high_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
739 740 741 742 743 744 745
			if (high_tpt > current_tpt)
				scale_action = 1;
			else {
				IWL_DEBUG_RATE
				    ("decrease rate because of high tpt\n");
				scale_action = -1;
			}
T
Tomas Winkler 已提交
746
		} else if (low_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
747 748 749 750 751 752 753 754 755
			if (low_tpt > current_tpt) {
				IWL_DEBUG_RATE
				    ("decrease rate because of low tpt\n");
				scale_action = -1;
			} else
				scale_action = 1;
		}
	}

756 757 758 759 760 761 762 763 764
	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;
		}
Z
Zhu Yi 已提交
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
	}

	switch (scale_action) {
	case -1:
		if (low != IWL_RATE_INVALID)
			index = low;
		break;

	case 1:
		if (high != IWL_RATE_INVALID)
			index = high;

		break;

	case 0:
	default:
		break;
	}

	IWL_DEBUG_RATE("Selected %d (action %d) - low %d high %d\n",
		       index, scale_action, low, high);

 out:

789
	rs_sta->last_txrate_idx = index;
T
Tomas Winkler 已提交
790
	if (sband->band == IEEE80211_BAND_5GHZ)
791 792
		info->control.rates[0].idx = rs_sta->last_txrate_idx -
				IWL_FIRST_OFDM_RATE;
793
	else
794
		info->control.rates[0].idx = rs_sta->last_txrate_idx;
795

Z
Zhu Yi 已提交
796 797 798
	IWL_DEBUG_RATE("leave: %d\n", index);
}

A
Abbas, Mohamed 已提交
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
#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

Z
Zhu Yi 已提交
853 854 855 856 857 858 859 860 861 862
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,
	.alloc = rs_alloc,
	.free = rs_free,
	.alloc_sta = rs_alloc_sta,
	.free_sta = rs_free_sta,
A
Abbas, Mohamed 已提交
863 864 865 866 867
#ifdef CONFIG_MAC80211_DEBUGFS
	.add_sta_debugfs = iwl3945_add_debugfs,
	.remove_sta_debugfs = iwl3945_remove_debugfs,
#endif

Z
Zhu Yi 已提交
868 869
};

C
Christoph Hellwig 已提交
870
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
Z
Zhu Yi 已提交
871
{
C
Christoph Hellwig 已提交
872
	struct iwl3945_priv *priv = hw->priv;
Z
Zhu Yi 已提交
873 874
	s32 rssi = 0;
	unsigned long flags;
875
	struct iwl3945_rs_sta *rs_sta;
876 877
	struct ieee80211_sta *sta;
	struct iwl3945_sta_priv *psta;
Z
Zhu Yi 已提交
878 879 880

	IWL_DEBUG_RATE("enter\n");

881 882
	rcu_read_lock();

883
	sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
884
	if (!sta) {
885
		rcu_read_unlock();
Z
Zhu Yi 已提交
886 887 888
		return;
	}

889
	psta = (void *) sta->drv_priv;
890
	rs_sta = psta->rs_sta;
Z
Zhu Yi 已提交
891

892
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
893

894
	rs_sta->tgg = 0;
895 896 897
	switch (priv->band) {
	case IEEE80211_BAND_2GHZ:
		/* TODO: this always does G, not a regression */
Z
Zhu Yi 已提交
898
		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
899 900
			rs_sta->tgg = 1;
			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
Z
Zhu Yi 已提交
901
		} else
902
			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
Z
Zhu Yi 已提交
903 904
		break;

905
	case IEEE80211_BAND_5GHZ:
906
		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
Z
Zhu Yi 已提交
907
		break;
908 909
	case IEEE80211_NUM_BANDS:
		BUG();
Z
Zhu Yi 已提交
910 911 912
		break;
	}

913
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
914 915 916 917 918 919 920

	rssi = priv->last_rx_rssi;
	if (rssi == 0)
		rssi = IWL_MIN_RSSI_VAL;

	IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);

921
	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
Z
Zhu Yi 已提交
922 923

	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
924 925
		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
		       iwl3945_rates[rs_sta->start_rate].plcp);
926
	rcu_read_unlock();
Z
Zhu Yi 已提交
927 928
}

929
int iwl3945_rate_control_register(void)
Z
Zhu Yi 已提交
930
{
931
	return ieee80211_rate_control_register(&rs_ops);
Z
Zhu Yi 已提交
932 933
}

934
void iwl3945_rate_control_unregister(void)
Z
Zhu Yi 已提交
935 936 937 938 939
{
	ieee80211_rate_control_unregister(&rs_ops);
}