iwl-3945-rs.c 23.9 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 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *
 * 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:
 * James P. Ketrenos <ipw2100-admin@linux.intel.com>
 * 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 339
static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
			 struct ieee80211_sta *sta, void *priv_sta)
Z
Zhu Yi 已提交
340
{
341
	struct iwl3945_rs_sta *rs_sta = priv_sta;
Z
Zhu Yi 已提交
342 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.. */

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

358
	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
359
	if (sband->band == IEEE80211_BAND_5GHZ)
360
		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
361

Z
Zhu Yi 已提交
362 363 364
	IWL_DEBUG_RATE("leave\n");
}

365
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
Z
Zhu Yi 已提交
366
{
367
	return hw->priv;
Z
Zhu Yi 已提交
368 369
}

370
/* rate scale requires free function to be implemented */
Z
Zhu Yi 已提交
371 372 373 374
static void rs_free(void *priv)
{
	return;
}
375 376

static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
Z
Zhu Yi 已提交
377
{
378
	struct iwl3945_rs_sta *rs_sta;
379
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
Z
Zhu Yi 已提交
380 381
	int i;

382 383 384 385 386
	/*
	 * XXX: If it's using sta->drv_priv anyway, it might
	 *	as well just put all the information there.
	 */

Z
Zhu Yi 已提交
387 388
	IWL_DEBUG_RATE("enter\n");

389 390
	rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
	if (!rs_sta) {
Z
Zhu Yi 已提交
391 392 393 394
		IWL_DEBUG_RATE("leave: ENOMEM\n");
		return NULL;
	}

395 396
	psta->rs_sta = rs_sta;

397
	spin_lock_init(&rs_sta->lock);
Z
Zhu Yi 已提交
398

399
	rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
400 401

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

404 405 406 407 408
	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 已提交
409

410 411 412
	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 已提交
413 414

	for (i = 0; i < IWL_RATE_COUNT; i++)
415
		iwl3945_clear_window(&rs_sta->win[i]);
Z
Zhu Yi 已提交
416 417 418

	IWL_DEBUG_RATE("leave\n");

419
	return rs_sta;
Z
Zhu Yi 已提交
420 421
}

422 423
static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
			void *priv_sta)
Z
Zhu Yi 已提交
424
{
425
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
426
	struct iwl3945_rs_sta *rs_sta = priv_sta;
Z
Zhu Yi 已提交
427

428 429
	psta->rs_sta = NULL;

Z
Zhu Yi 已提交
430
	IWL_DEBUG_RATE("enter\n");
431 432
	del_timer_sync(&rs_sta->rate_scale_flush);
	kfree(rs_sta);
Z
Zhu Yi 已提交
433 434 435
	IWL_DEBUG_RATE("leave\n");
}

436

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

T
Tomas Winkler 已提交
454 455
	IWL_DEBUG_RATE("enter\n");

456
	retries = info->status.rates[0].count;
457 458

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

464
	if (!priv_sta) {
Z
Zhu Yi 已提交
465 466 467 468
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
		return;
	}

469
	rs_sta->tx_packets++;
Z
Zhu Yi 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483

	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)
	 */
484 485 486
	while (retries > 1) {
		if ((retries - 1) < priv->retry_rate) {
			current_count = (retries - 1);
Z
Zhu Yi 已提交
487 488 489
			last_index = scale_rate_index;
		} else {
			current_count = priv->retry_rate;
490
			last_index = iwl3945_rs_next_rate(priv,
491
							 scale_rate_index);
Z
Zhu Yi 已提交
492 493 494 495
		}

		/* Update this rate accounting for as many retries
		 * as was used for it (per current_count) */
496 497
		iwl3945_collect_tx_data(rs_sta,
				    &rs_sta->win[scale_rate_index],
498
				    0, current_count, scale_rate_index);
Z
Zhu Yi 已提交
499 500 501 502 503
		IWL_DEBUG_RATE("Update rate %d for %d retries.\n",
			       scale_rate_index, current_count);

		retries -= current_count;

504
		scale_rate_index = last_index;
Z
Zhu Yi 已提交
505 506
	}

507

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

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

522
	if (!rs_sta->flush_pending &&
523
	    time_after(jiffies, rs_sta->last_flush +
524
		       rs_sta->flush_time)) {
Z
Zhu Yi 已提交
525

526
		rs_sta->last_partial_flush = jiffies;
527 528 529
		rs_sta->flush_pending = 1;
		mod_timer(&rs_sta->rate_scale_flush,
			  jiffies + rs_sta->flush_time);
Z
Zhu Yi 已提交
530 531
	}

532
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
533 534 535 536 537 538

	IWL_DEBUG_RATE("leave\n");

	return;
}

539
static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
540
				 u8 index, u16 rate_mask, enum ieee80211_band band)
Z
Zhu Yi 已提交
541 542 543 544
{
	u8 high = IWL_RATE_INVALID;
	u8 low = IWL_RATE_INVALID;

545
	/* 802.11A walks to the next literal adjacent rate in
Z
Zhu Yi 已提交
546
	 * the rate table */
547
	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
Z
Zhu Yi 已提交
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
		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) {
574
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
575
			low = iwl3945_rates[low].prev_rs_tgg;
Z
Zhu Yi 已提交
576
		else
C
Christoph Hellwig 已提交
577
			low = iwl3945_rates[low].prev_rs;
Z
Zhu Yi 已提交
578 579 580 581 582 583 584 585 586
		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) {
587
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
588
			high = iwl3945_rates[high].next_rs_tgg;
Z
Zhu Yi 已提交
589
		else
C
Christoph Hellwig 已提交
590
			high = iwl3945_rates[high].next_rs;
Z
Zhu Yi 已提交
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
		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
 *
 */
617 618
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
Z
Zhu Yi 已提交
619
{
620 621
	struct ieee80211_supported_band *sband = txrc->sband;
	struct sk_buff *skb = txrc->skb;
Z
Zhu Yi 已提交
622 623 624 625
	u8 low = IWL_RATE_INVALID;
	u8 high = IWL_RATE_INVALID;
	u16 high_low;
	int index;
626
	struct iwl3945_rs_sta *rs_sta = priv_sta;
C
Christoph Hellwig 已提交
627
	struct iwl3945_rate_scale_data *window = NULL;
T
Tomas Winkler 已提交
628 629 630
	int current_tpt = IWL_INV_TPT;
	int low_tpt = IWL_INV_TPT;
	int high_tpt = IWL_INV_TPT;
Z
Zhu Yi 已提交
631 632 633 634
	u32 fail_count;
	s8 scale_action = 0;
	unsigned long flags;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
635
	u16 fc, rate_mask;
636
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
637
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Z
Zhu Yi 已提交
638 639 640

	IWL_DEBUG_RATE("enter\n");

641 642 643 644 645
	/* 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) ||
646
	    !sta || !priv_sta) {
Z
Zhu Yi 已提交
647
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
648
		info->control.rates[0].idx = rate_lowest_index(sband, sta);
649
		return;
Z
Zhu Yi 已提交
650 651
	}

652
	rate_mask = sta->supp_rates[sband->band];
653
	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
654

T
Tomas Winkler 已提交
655
	if (sband->band == IEEE80211_BAND_5GHZ)
656
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
657

658
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
659
	    !rs_sta->ibss_sta_added) {
C
Christoph Hellwig 已提交
660
		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
661 662

		if (sta_id == IWL_INVALID_STATION) {
J
Johannes Berg 已提交
663 664
			IWL_DEBUG_RATE("LQ: ADD station %pm\n",
				       hdr->addr1);
C
Christoph Hellwig 已提交
665
			sta_id = iwl3945_add_station(priv,
Z
Zhu Yi 已提交
666 667 668
				    hdr->addr1, 0, CMD_ASYNC);
		}
		if (sta_id != IWL_INVALID_STATION)
669
			rs_sta->ibss_sta_added = 1;
Z
Zhu Yi 已提交
670 671
	}

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

674 675 676
	/* for recent assoc, choose best rate regarding
	 * to rssi value
	 */
677
	if (rs_sta->start_rate != IWL_RATE_INVALID) {
678 679 680
		if (rs_sta->start_rate < index &&
		   (rate_mask & (1 << rs_sta->start_rate)))
			index = rs_sta->start_rate;
681
		rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
682 683
	}

684
	window = &(rs_sta->win[index]);
Z
Zhu Yi 已提交
685 686 687 688 689

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

	if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
690
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
691 692 693 694 695 696 697

		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,
698
			       rs_sta->expected_tpt ? "not " : "");
Z
Zhu Yi 已提交
699 700 701 702 703 704
		goto out;

	}

	current_tpt = window->average_tpt;

705
	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
T
Tomas Winkler 已提交
706
					     sband->band);
Z
Zhu Yi 已提交
707 708 709 710
	low = high_low & 0xff;
	high = (high_low >> 8) & 0xff;

	if (low != IWL_RATE_INVALID)
711
		low_tpt = rs_sta->win[low].average_tpt;
Z
Zhu Yi 已提交
712 713

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

716
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
717 718 719 720 721 722

	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 已提交
723
	} else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
Z
Zhu Yi 已提交
724
		scale_action = 1;
T
Tomas Winkler 已提交
725 726
	else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
Z
Zhu Yi 已提交
727 728 729 730 731
		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 已提交
732
		if (high_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
733 734 735 736 737 738 739
			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 已提交
740
		} else if (low_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
741 742 743 744 745 746 747 748 749
			if (low_tpt > current_tpt) {
				IWL_DEBUG_RATE
				    ("decrease rate because of low tpt\n");
				scale_action = -1;
			} else
				scale_action = 1;
		}
	}

750 751 752 753 754 755 756 757 758
	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 已提交
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
	}

	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:

783
	rs_sta->last_txrate_idx = index;
T
Tomas Winkler 已提交
784
	if (sband->band == IEEE80211_BAND_5GHZ)
785 786
		info->control.rates[0].idx = rs_sta->last_txrate_idx -
				IWL_FIRST_OFDM_RATE;
787
	else
788
		info->control.rates[0].idx = rs_sta->last_txrate_idx;
789

Z
Zhu Yi 已提交
790 791 792
	IWL_DEBUG_RATE("leave: %d\n", index);
}

A
Abbas, Mohamed 已提交
793 794 795 796 797 798 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
#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 已提交
847 848 849 850 851 852 853 854 855 856
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 已提交
857 858 859 860 861
#ifdef CONFIG_MAC80211_DEBUGFS
	.add_sta_debugfs = iwl3945_add_debugfs,
	.remove_sta_debugfs = iwl3945_remove_debugfs,
#endif

Z
Zhu Yi 已提交
862 863
};

C
Christoph Hellwig 已提交
864
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
Z
Zhu Yi 已提交
865
{
C
Christoph Hellwig 已提交
866
	struct iwl3945_priv *priv = hw->priv;
Z
Zhu Yi 已提交
867 868
	s32 rssi = 0;
	unsigned long flags;
869
	struct iwl3945_rs_sta *rs_sta;
870 871
	struct ieee80211_sta *sta;
	struct iwl3945_sta_priv *psta;
Z
Zhu Yi 已提交
872 873 874

	IWL_DEBUG_RATE("enter\n");

875 876
	rcu_read_lock();

877
	sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
878
	if (!sta) {
879
		rcu_read_unlock();
Z
Zhu Yi 已提交
880 881 882
		return;
	}

883
	psta = (void *) sta->drv_priv;
884
	rs_sta = psta->rs_sta;
Z
Zhu Yi 已提交
885

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

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

899
	case IEEE80211_BAND_5GHZ:
900
		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
Z
Zhu Yi 已提交
901
		break;
902 903
	case IEEE80211_NUM_BANDS:
		BUG();
Z
Zhu Yi 已提交
904 905 906
		break;
	}

907
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
908 909 910 911 912 913 914

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

915
	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
Z
Zhu Yi 已提交
916 917

	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
918 919
		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
		       iwl3945_rates[rs_sta->start_rate].plcp);
920
	rcu_read_unlock();
Z
Zhu Yi 已提交
921 922
}

923
int iwl3945_rate_control_register(void)
Z
Zhu Yi 已提交
924
{
925
	return ieee80211_rate_control_register(&rs_ops);
Z
Zhu Yi 已提交
926 927
}

928
void iwl3945_rate_control_unregister(void)
Z
Zhu Yi 已提交
929 930 931 932 933
{
	ieee80211_rate_control_unregister(&rs_ops);
}