iwl-3945-rs.c 24.2 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-commands.h"
40
#include "iwl-3945.h"
Z
Zhu Yi 已提交
41 42 43

#define RS_NAME "iwl-3945-rs"

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

53
struct iwl3945_rs_sta {
Z
Zhu Yi 已提交
54 55 56 57 58 59 60 61 62 63 64 65
	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 已提交
66
	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
A
Abbas, Mohamed 已提交
67 68 69
#ifdef CONFIG_MAC80211_DEBUGFS
	struct dentry *rs_sta_dbgfs_stats_table_file;
#endif
70 71 72

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

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

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

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

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

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

C
Christoph Hellwig 已提交
96
static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
Z
Zhu Yi 已提交
97 98 99 100 101 102 103 104 105 106
	{-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 已提交
107
static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
Z
Zhu Yi 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120
	{-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
121
#define IWL_RATE_FLUSH       	 (3*HZ)
Z
Zhu Yi 已提交
122 123
#define IWL_RATE_WIN_FLUSH       (HZ/2)
#define IWL_RATE_HIGH_TH          11520
124 125
#define IWL_SUCCESS_UP_TH	   8960
#define IWL_SUCCESS_DOWN_TH	  10880
Z
Zhu Yi 已提交
126 127 128 129
#define IWL_RATE_MIN_FAILURE_TH       8
#define IWL_RATE_MIN_SUCCESS_TH       8
#define IWL_RATE_DECREASE_TH       1920

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

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

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

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

	default:
151
		BUG();
Z
Zhu Yi 已提交
152 153 154 155 156 157 158 159 160 161 162
		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 已提交
163
static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
Z
Zhu Yi 已提交
164 165 166
{
	window->data = 0;
	window->success_counter = 0;
T
Tomas Winkler 已提交
167
	window->success_ratio = -1;
Z
Zhu Yi 已提交
168
	window->counter = 0;
T
Tomas Winkler 已提交
169
	window->average_tpt = IWL_INV_TPT;
Z
Zhu Yi 已提交
170 171 172 173
	window->stamp = 0;
}

/**
C
Christoph Hellwig 已提交
174
 * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
Z
Zhu Yi 已提交
175 176 177 178 179
 *
 * 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.
 */
180
static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
Z
Zhu Yi 已提交
181 182 183 184 185 186 187 188 189 190 191
{
	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++) {
192
		if (!rs_sta->win[i].counter)
Z
Zhu Yi 已提交
193 194
			continue;

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

	return unflushed;
}

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

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

	IWL_DEBUG_RATE("enter\n");

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

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

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

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

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

		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) {
246
			duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
Z
Zhu Yi 已提交
247 248
			if (duration < IWL_RATE_FLUSH_MIN)
				duration = IWL_RATE_FLUSH_MIN;
249 250
			else if (duration > IWL_RATE_FLUSH_MAX)
				duration = IWL_RATE_FLUSH_MAX;
Z
Zhu Yi 已提交
251 252 253
		} else
			duration = IWL_RATE_FLUSH_MAX;

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

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

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

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

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

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

	IWL_DEBUG_RATE("leave\n");
}

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

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

296
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
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 325
	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;

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

	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 已提交
337 338
}

339
static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
340
			 struct ieee80211_sta *sta, void *priv_sta)
Z
Zhu Yi 已提交
341
{
342
	struct iwl3945_rs_sta *rs_sta = priv_sta;
343
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
Z
Zhu Yi 已提交
344 345 346 347 348 349 350 351 352
	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.. */

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

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

368

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

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

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

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

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

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

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

402 403
	psta->rs_sta = rs_sta;

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

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

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

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

417 418 419
	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 已提交
420 421

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

	IWL_DEBUG_RATE("leave\n");

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

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

435 436
	psta->rs_sta = NULL;

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

443

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

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

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

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

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

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

	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)
	 */
491 492 493
	while (retries > 1) {
		if ((retries - 1) < priv->retry_rate) {
			current_count = (retries - 1);
Z
Zhu Yi 已提交
494 495 496
			last_index = scale_rate_index;
		} else {
			current_count = priv->retry_rate;
497
			last_index = iwl3945_rs_next_rate(priv,
498
							 scale_rate_index);
Z
Zhu Yi 已提交
499 500 501 502
		}

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

		retries -= current_count;

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

514

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

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

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

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

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

	IWL_DEBUG_RATE("leave\n");

	return;
}

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

552
	/* 802.11A walks to the next literal adjacent rate in
Z
Zhu Yi 已提交
553
	 * the rate table */
554
	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
Z
Zhu Yi 已提交
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 580
		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) {
581
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
582
			low = iwl3945_rates[low].prev_rs_tgg;
Z
Zhu Yi 已提交
583
		else
C
Christoph Hellwig 已提交
584
			low = iwl3945_rates[low].prev_rs;
Z
Zhu Yi 已提交
585 586 587 588 589 590 591 592 593
		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) {
594
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
595
			high = iwl3945_rates[high].next_rs_tgg;
Z
Zhu Yi 已提交
596
		else
C
Christoph Hellwig 已提交
597
			high = iwl3945_rates[high].next_rs;
Z
Zhu Yi 已提交
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 623
		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
 *
 */
624 625
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
Z
Zhu Yi 已提交
626
{
627 628
	struct ieee80211_supported_band *sband = txrc->sband;
	struct sk_buff *skb = txrc->skb;
Z
Zhu Yi 已提交
629 630 631 632
	u8 low = IWL_RATE_INVALID;
	u8 high = IWL_RATE_INVALID;
	u16 high_low;
	int index;
633
	struct iwl3945_rs_sta *rs_sta = priv_sta;
C
Christoph Hellwig 已提交
634
	struct iwl3945_rate_scale_data *window = NULL;
T
Tomas Winkler 已提交
635 636 637
	int current_tpt = IWL_INV_TPT;
	int low_tpt = IWL_INV_TPT;
	int high_tpt = IWL_INV_TPT;
Z
Zhu Yi 已提交
638 639 640 641
	u32 fail_count;
	s8 scale_action = 0;
	unsigned long flags;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
642 643
	u16 fc;
	u16 rate_mask = 0;
644
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
645
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Z
Zhu Yi 已提交
646 647 648

	IWL_DEBUG_RATE("enter\n");

649 650 651
	if (sta)
		rate_mask = sta->supp_rates[sband->band];

652 653 654 655 656
	/* 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) ||
657
	    !sta || !priv_sta) {
Z
Zhu Yi 已提交
658
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
659 660 661 662 663 664
		if (!rate_mask)
			info->control.rates[0].idx =
					rate_lowest_index(sband, NULL);
		else
			info->control.rates[0].idx =
					rate_lowest_index(sband, sta);
665
		return;
Z
Zhu Yi 已提交
666 667
	}

668
	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
669

T
Tomas Winkler 已提交
670
	if (sband->band == IEEE80211_BAND_5GHZ)
671
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
672

673
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
674
	    !rs_sta->ibss_sta_added) {
C
Christoph Hellwig 已提交
675
		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
676 677

		if (sta_id == IWL_INVALID_STATION) {
J
Johannes Berg 已提交
678 679
			IWL_DEBUG_RATE("LQ: ADD station %pm\n",
				       hdr->addr1);
C
Christoph Hellwig 已提交
680
			sta_id = iwl3945_add_station(priv,
Z
Zhu Yi 已提交
681 682 683
				    hdr->addr1, 0, CMD_ASYNC);
		}
		if (sta_id != IWL_INVALID_STATION)
684
			rs_sta->ibss_sta_added = 1;
Z
Zhu Yi 已提交
685 686
	}

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

689 690 691
	/* for recent assoc, choose best rate regarding
	 * to rssi value
	 */
692
	if (rs_sta->start_rate != IWL_RATE_INVALID) {
693 694 695
		if (rs_sta->start_rate < index &&
		   (rate_mask & (1 << rs_sta->start_rate)))
			index = rs_sta->start_rate;
696
		rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
697 698
	}

699
	window = &(rs_sta->win[index]);
Z
Zhu Yi 已提交
700 701 702 703 704

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

	if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
705
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
706 707 708 709 710 711 712

		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,
713
			       rs_sta->expected_tpt ? "not " : "");
Z
Zhu Yi 已提交
714 715 716 717 718 719
		goto out;

	}

	current_tpt = window->average_tpt;

720
	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
T
Tomas Winkler 已提交
721
					     sband->band);
Z
Zhu Yi 已提交
722 723 724 725
	low = high_low & 0xff;
	high = (high_low >> 8) & 0xff;

	if (low != IWL_RATE_INVALID)
726
		low_tpt = rs_sta->win[low].average_tpt;
Z
Zhu Yi 已提交
727 728

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

731
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
732 733 734 735 736 737

	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 已提交
738
	} else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
Z
Zhu Yi 已提交
739
		scale_action = 1;
T
Tomas Winkler 已提交
740 741
	else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
Z
Zhu Yi 已提交
742 743 744 745 746
		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 已提交
747
		if (high_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
748 749 750 751 752 753 754
			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 已提交
755
		} else if (low_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
756 757 758 759 760 761 762 763 764
			if (low_tpt > current_tpt) {
				IWL_DEBUG_RATE
				    ("decrease rate because of low tpt\n");
				scale_action = -1;
			} else
				scale_action = 1;
		}
	}

765 766 767 768 769 770 771 772 773
	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 已提交
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
	}

	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:

798
	rs_sta->last_txrate_idx = index;
T
Tomas Winkler 已提交
799
	if (sband->band == IEEE80211_BAND_5GHZ)
800 801
		info->control.rates[0].idx = rs_sta->last_txrate_idx -
				IWL_FIRST_OFDM_RATE;
802
	else
803
		info->control.rates[0].idx = rs_sta->last_txrate_idx;
804

Z
Zhu Yi 已提交
805 806 807
	IWL_DEBUG_RATE("leave: %d\n", index);
}

A
Abbas, Mohamed 已提交
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 853 854 855 856 857 858 859 860 861
#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 已提交
862 863 864 865 866 867 868 869 870 871
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 已提交
872 873 874 875 876
#ifdef CONFIG_MAC80211_DEBUGFS
	.add_sta_debugfs = iwl3945_add_debugfs,
	.remove_sta_debugfs = iwl3945_remove_debugfs,
#endif

Z
Zhu Yi 已提交
877 878
};

C
Christoph Hellwig 已提交
879
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
Z
Zhu Yi 已提交
880
{
C
Christoph Hellwig 已提交
881
	struct iwl3945_priv *priv = hw->priv;
Z
Zhu Yi 已提交
882 883
	s32 rssi = 0;
	unsigned long flags;
884
	struct iwl3945_rs_sta *rs_sta;
885 886
	struct ieee80211_sta *sta;
	struct iwl3945_sta_priv *psta;
Z
Zhu Yi 已提交
887 888 889

	IWL_DEBUG_RATE("enter\n");

890 891
	rcu_read_lock();

892
	sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
893
	if (!sta) {
894
		rcu_read_unlock();
Z
Zhu Yi 已提交
895 896 897
		return;
	}

898
	psta = (void *) sta->drv_priv;
899
	rs_sta = psta->rs_sta;
Z
Zhu Yi 已提交
900

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

903
	rs_sta->tgg = 0;
904 905 906
	switch (priv->band) {
	case IEEE80211_BAND_2GHZ:
		/* TODO: this always does G, not a regression */
Z
Zhu Yi 已提交
907
		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
908 909
			rs_sta->tgg = 1;
			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
Z
Zhu Yi 已提交
910
		} else
911
			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
Z
Zhu Yi 已提交
912 913
		break;

914
	case IEEE80211_BAND_5GHZ:
915
		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
Z
Zhu Yi 已提交
916
		break;
917 918
	case IEEE80211_NUM_BANDS:
		BUG();
Z
Zhu Yi 已提交
919 920 921
		break;
	}

922
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
923 924 925 926 927 928 929

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

930
	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
Z
Zhu Yi 已提交
931 932

	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
933 934
		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
		       iwl3945_rates[rs_sta->start_rate].plcp);
935
	rcu_read_unlock();
Z
Zhu Yi 已提交
936 937
}

938
int iwl3945_rate_control_register(void)
Z
Zhu Yi 已提交
939
{
940
	return ieee80211_rate_control_register(&rs_ops);
Z
Zhu Yi 已提交
941 942
}

943
void iwl3945_rate_control_unregister(void)
Z
Zhu Yi 已提交
944 945 946 947 948
{
	ieee80211_rate_control_unregister(&rs_ops);
}