iwl-3945-rs.c 24.5 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
	spinlock_t lock;
55
	struct iwl3945_priv *priv;
Z
Zhu Yi 已提交
56 57 58 59 60 61 62 63 64 65 66
	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 已提交
67
	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
A
Abbas, Mohamed 已提交
68 69 70
#ifdef CONFIG_MAC80211_DEBUGFS
	struct dentry *rs_sta_dbgfs_stats_table_file;
#endif
71 72 73

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

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

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

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

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

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

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

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

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

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

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

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

/**
C
Christoph Hellwig 已提交
175
 * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
Z
Zhu Yi 已提交
176 177 178 179 180
 *
 * 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.
 */
181
static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
Z
Zhu Yi 已提交
182 183 184 185
{
	int unflushed = 0;
	int i;
	unsigned long flags;
186
	struct iwl3945_priv *priv = rs_sta->priv;
Z
Zhu Yi 已提交
187 188 189 190 191 192 193

	/*
	 * 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++) {
194
		if (!rs_sta->win[i].counter)
Z
Zhu Yi 已提交
195 196
			continue;

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

	return unflushed;
}

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

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

	IWL_DEBUG_RATE("enter\n");

226
	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
Z
Zhu Yi 已提交
227

228
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
229 230

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

233
	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
Z
Zhu Yi 已提交
234 235 236

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

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

257
		rs_sta->flush_time = msecs_to_jiffies(duration);
Z
Zhu Yi 已提交
258 259 260 261

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

262 263
		mod_timer(&rs_sta->rate_scale_flush, jiffies +
			  rs_sta->flush_time);
Z
Zhu Yi 已提交
264

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

273
	rs_sta->last_flush = jiffies;
Z
Zhu Yi 已提交
274

275
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
276 277 278 279 280

	IWL_DEBUG_RATE("leave\n");
}

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

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

300
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
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 326 327 328 329
	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;

	}
330 331 332 333 334 335 336 337 338 339 340

	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 已提交
341 342
}

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

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

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

372

Z
Zhu Yi 已提交
373 374 375
	IWL_DEBUG_RATE("leave\n");
}

376
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
Z
Zhu Yi 已提交
377
{
378
	return hw->priv;
Z
Zhu Yi 已提交
379 380
}

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

387
static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
Z
Zhu Yi 已提交
388
{
389
	struct iwl3945_rs_sta *rs_sta;
390
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
391
	struct iwl3945_priv *priv = iwl_priv;
Z
Zhu Yi 已提交
392 393
	int i;

394 395 396 397 398
	/*
	 * XXX: If it's using sta->drv_priv anyway, it might
	 *	as well just put all the information there.
	 */

Z
Zhu Yi 已提交
399 400
	IWL_DEBUG_RATE("enter\n");

401 402
	rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
	if (!rs_sta) {
Z
Zhu Yi 已提交
403 404 405 406
		IWL_DEBUG_RATE("leave: ENOMEM\n");
		return NULL;
	}

407 408
	psta->rs_sta = rs_sta;

409
	spin_lock_init(&rs_sta->lock);
Z
Zhu Yi 已提交
410

411 412
	rs_sta->priv = priv;

413
	rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
414 415

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

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

424 425 426
	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 已提交
427 428

	for (i = 0; i < IWL_RATE_COUNT; i++)
429
		iwl3945_clear_window(&rs_sta->win[i]);
Z
Zhu Yi 已提交
430 431 432

	IWL_DEBUG_RATE("leave\n");

433
	return rs_sta;
Z
Zhu Yi 已提交
434 435
}

436
static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
437
			void *priv_sta)
Z
Zhu Yi 已提交
438
{
439
	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
440
	struct iwl3945_rs_sta *rs_sta = priv_sta;
441
	struct iwl3945_priv *priv = rs_sta->priv;
Z
Zhu Yi 已提交
442

443 444
	psta->rs_sta = NULL;

Z
Zhu Yi 已提交
445
	IWL_DEBUG_RATE("enter\n");
446 447
	del_timer_sync(&rs_sta->rate_scale_flush);
	kfree(rs_sta);
Z
Zhu Yi 已提交
448 449 450
	IWL_DEBUG_RATE("leave\n");
}

451

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

T
Tomas Winkler 已提交
469 470
	IWL_DEBUG_RATE("enter\n");

471
	retries = info->status.rates[0].count;
472 473

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

479
	if (!priv_sta) {
Z
Zhu Yi 已提交
480 481 482 483
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
		return;
	}

484
	rs_sta->tx_packets++;
Z
Zhu Yi 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497 498

	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)
	 */
499 500 501
	while (retries > 1) {
		if ((retries - 1) < priv->retry_rate) {
			current_count = (retries - 1);
Z
Zhu Yi 已提交
502 503 504
			last_index = scale_rate_index;
		} else {
			current_count = priv->retry_rate;
505
			last_index = iwl3945_rs_next_rate(priv,
506
							 scale_rate_index);
Z
Zhu Yi 已提交
507 508 509 510
		}

		/* Update this rate accounting for as many retries
		 * as was used for it (per current_count) */
511 512
		iwl3945_collect_tx_data(rs_sta,
				    &rs_sta->win[scale_rate_index],
513
				    0, current_count, scale_rate_index);
Z
Zhu Yi 已提交
514 515 516 517 518
		IWL_DEBUG_RATE("Update rate %d for %d retries.\n",
			       scale_rate_index, current_count);

		retries -= current_count;

519
		scale_rate_index = last_index;
Z
Zhu Yi 已提交
520 521
	}

522

Z
Zhu Yi 已提交
523 524 525
	/* Update the last index window with success/failure based on ACK */
	IWL_DEBUG_RATE("Update rate %d with %s.\n",
		       last_index,
526
		       (info->flags & IEEE80211_TX_STAT_ACK) ?
Z
Zhu Yi 已提交
527
		       "success" : "failure");
528 529
	iwl3945_collect_tx_data(rs_sta,
			    &rs_sta->win[last_index],
530
			    info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
Z
Zhu Yi 已提交
531 532 533 534

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

537
	if (!rs_sta->flush_pending &&
538
	    time_after(jiffies, rs_sta->last_flush +
539
		       rs_sta->flush_time)) {
Z
Zhu Yi 已提交
540

541
		rs_sta->last_partial_flush = jiffies;
542 543 544
		rs_sta->flush_pending = 1;
		mod_timer(&rs_sta->rate_scale_flush,
			  jiffies + rs_sta->flush_time);
Z
Zhu Yi 已提交
545 546
	}

547
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
548 549 550 551 552 553

	IWL_DEBUG_RATE("leave\n");

	return;
}

554
static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
555
				 u8 index, u16 rate_mask, enum ieee80211_band band)
Z
Zhu Yi 已提交
556 557 558
{
	u8 high = IWL_RATE_INVALID;
	u8 low = IWL_RATE_INVALID;
559
	struct iwl3945_priv *priv = rs_sta->priv;
Z
Zhu Yi 已提交
560

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

	IWL_DEBUG_RATE("enter\n");

658 659 660
	if (sta)
		rate_mask = sta->supp_rates[sband->band];

661 662 663 664 665
	/* 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) ||
666
	    !sta || !priv_sta) {
Z
Zhu Yi 已提交
667
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
668 669 670 671 672 673
		if (!rate_mask)
			info->control.rates[0].idx =
					rate_lowest_index(sband, NULL);
		else
			info->control.rates[0].idx =
					rate_lowest_index(sband, sta);
674
		return;
Z
Zhu Yi 已提交
675 676
	}

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

T
Tomas Winkler 已提交
679
	if (sband->band == IEEE80211_BAND_5GHZ)
680
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
681

682
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
683
	    !rs_sta->ibss_sta_added) {
C
Christoph Hellwig 已提交
684
		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
685 686

		if (sta_id == IWL_INVALID_STATION) {
J
Johannes Berg 已提交
687 688
			IWL_DEBUG_RATE("LQ: ADD station %pm\n",
				       hdr->addr1);
C
Christoph Hellwig 已提交
689
			sta_id = iwl3945_add_station(priv,
Z
Zhu Yi 已提交
690 691 692
				    hdr->addr1, 0, CMD_ASYNC);
		}
		if (sta_id != IWL_INVALID_STATION)
693
			rs_sta->ibss_sta_added = 1;
Z
Zhu Yi 已提交
694 695
	}

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

698 699 700
	/* for recent assoc, choose best rate regarding
	 * to rssi value
	 */
701
	if (rs_sta->start_rate != IWL_RATE_INVALID) {
702 703 704
		if (rs_sta->start_rate < index &&
		   (rate_mask & (1 << rs_sta->start_rate)))
			index = rs_sta->start_rate;
705
		rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
706 707
	}

708
	window = &(rs_sta->win[index]);
Z
Zhu Yi 已提交
709 710 711 712 713

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

	if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
714
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
715 716 717 718 719 720 721

		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,
722
			       rs_sta->expected_tpt ? "not " : "");
Z
Zhu Yi 已提交
723 724 725 726 727 728
		goto out;

	}

	current_tpt = window->average_tpt;

729
	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
T
Tomas Winkler 已提交
730
					     sband->band);
Z
Zhu Yi 已提交
731 732 733 734
	low = high_low & 0xff;
	high = (high_low >> 8) & 0xff;

	if (low != IWL_RATE_INVALID)
735
		low_tpt = rs_sta->win[low].average_tpt;
Z
Zhu Yi 已提交
736 737

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

740
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
741 742 743 744 745 746

	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 已提交
747
	} else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
Z
Zhu Yi 已提交
748
		scale_action = 1;
T
Tomas Winkler 已提交
749 750
	else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
Z
Zhu Yi 已提交
751 752 753 754 755
		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 已提交
756
		if (high_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
757 758 759 760 761 762 763
			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 已提交
764
		} else if (low_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
765 766 767 768 769 770 771 772 773
			if (low_tpt > current_tpt) {
				IWL_DEBUG_RATE
				    ("decrease rate because of low tpt\n");
				scale_action = -1;
			} else
				scale_action = 1;
		}
	}

774 775 776 777 778 779 780 781 782
	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 已提交
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
	}

	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:

807
	rs_sta->last_txrate_idx = index;
T
Tomas Winkler 已提交
808
	if (sband->band == IEEE80211_BAND_5GHZ)
809 810
		info->control.rates[0].idx = rs_sta->last_txrate_idx -
				IWL_FIRST_OFDM_RATE;
811
	else
812
		info->control.rates[0].idx = rs_sta->last_txrate_idx;
813

Z
Zhu Yi 已提交
814 815 816
	IWL_DEBUG_RATE("leave: %d\n", index);
}

A
Abbas, Mohamed 已提交
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 862 863 864 865 866 867 868 869 870
#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 已提交
871 872 873 874 875 876 877 878 879 880
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 已提交
881 882 883 884 885
#ifdef CONFIG_MAC80211_DEBUGFS
	.add_sta_debugfs = iwl3945_add_debugfs,
	.remove_sta_debugfs = iwl3945_remove_debugfs,
#endif

Z
Zhu Yi 已提交
886 887
};

C
Christoph Hellwig 已提交
888
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
Z
Zhu Yi 已提交
889
{
C
Christoph Hellwig 已提交
890
	struct iwl3945_priv *priv = hw->priv;
Z
Zhu Yi 已提交
891 892
	s32 rssi = 0;
	unsigned long flags;
893
	struct iwl3945_rs_sta *rs_sta;
894 895
	struct ieee80211_sta *sta;
	struct iwl3945_sta_priv *psta;
Z
Zhu Yi 已提交
896 897 898

	IWL_DEBUG_RATE("enter\n");

899 900
	rcu_read_lock();

901
	sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
902
	if (!sta) {
903
		rcu_read_unlock();
Z
Zhu Yi 已提交
904 905 906
		return;
	}

907
	psta = (void *) sta->drv_priv;
908
	rs_sta = psta->rs_sta;
Z
Zhu Yi 已提交
909

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

912
	rs_sta->tgg = 0;
913 914 915
	switch (priv->band) {
	case IEEE80211_BAND_2GHZ:
		/* TODO: this always does G, not a regression */
Z
Zhu Yi 已提交
916
		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
917 918
			rs_sta->tgg = 1;
			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
Z
Zhu Yi 已提交
919
		} else
920
			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
Z
Zhu Yi 已提交
921 922
		break;

923
	case IEEE80211_BAND_5GHZ:
924
		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
Z
Zhu Yi 已提交
925
		break;
926 927
	case IEEE80211_NUM_BANDS:
		BUG();
Z
Zhu Yi 已提交
928 929 930
		break;
	}

931
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
932 933 934 935 936 937 938

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

939
	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
Z
Zhu Yi 已提交
940 941

	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
942 943
		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
		       iwl3945_rates[rs_sta->start_rate].plcp);
944
	rcu_read_unlock();
Z
Zhu Yi 已提交
945 946
}

947
int iwl3945_rate_control_register(void)
Z
Zhu Yi 已提交
948
{
949
	return ieee80211_rate_control_register(&rs_ops);
Z
Zhu Yi 已提交
950 951
}

952
void iwl3945_rate_control_unregister(void)
Z
Zhu Yi 已提交
953 954 955 956 957
{
	ieee80211_rate_control_unregister(&rs_ops);
}