iwl-3945-rs.c 25.3 KB
Newer Older
Z
Zhu Yi 已提交
1 2
/******************************************************************************
 *
3
 * Copyright(c) 2005 - 2009 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 iwl_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;
67
	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
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
};

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

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

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

88
static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
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
#define IWL_RATE_WIN_FLUSH       (HZ/2)
124
#define IWL39_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;
170
	window->average_tpt = IWL_INVALID_VALUE;
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 iwl_priv *priv __maybe_unused = rs_sta->priv;
Z
Zhu Yi 已提交
187 188 189 190 191 192

	/*
	 * 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
	 */
193
	for (i = 0; i < IWL_RATE_COUNT_3945; 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 iwl_priv *priv __maybe_unused = 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 iwl_priv *priv __maybe_unused = 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

	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
337
		window->average_tpt = IWL_INVALID_VALUE;
338 339 340

	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 iwl_priv *priv = (struct iwl_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 iwl_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_3945; 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 iwl_priv *priv __maybe_unused = 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
 *
455
 * NOTE: Uses iwl_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;
465
	struct iwl_priv *priv = (struct iwl_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;
474
	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
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 iwl_priv *priv __maybe_unused = 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
		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;
578 579
		for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
		     i++, mask <<= 1) {
Z
Zhu Yi 已提交
580 581 582 583 584 585 586 587 588 589 590
			if (rate_mask & mask) {
				high = i;
				break;
			}
		}

		return (high << 8) | low;
	}

	low = index;
	while (low != IWL_RATE_INVALID) {
591
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
592
			low = iwl3945_rates[low].prev_rs_tgg;
Z
Zhu Yi 已提交
593
		else
C
Christoph Hellwig 已提交
594
			low = iwl3945_rates[low].prev_rs;
Z
Zhu Yi 已提交
595 596 597 598 599 600 601 602 603
		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) {
604
		if (rs_sta->tgg)
C
Christoph Hellwig 已提交
605
			high = iwl3945_rates[high].next_rs_tgg;
Z
Zhu Yi 已提交
606
		else
C
Christoph Hellwig 已提交
607
			high = iwl3945_rates[high].next_rs;
Z
Zhu Yi 已提交
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 633
		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
 *
 */
634 635
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
Z
Zhu Yi 已提交
636
{
637 638
	struct ieee80211_supported_band *sband = txrc->sband;
	struct sk_buff *skb = txrc->skb;
Z
Zhu Yi 已提交
639 640 641 642
	u8 low = IWL_RATE_INVALID;
	u8 high = IWL_RATE_INVALID;
	u16 high_low;
	int index;
643
	struct iwl3945_rs_sta *rs_sta = priv_sta;
C
Christoph Hellwig 已提交
644
	struct iwl3945_rate_scale_data *window = NULL;
645 646 647
	int current_tpt = IWL_INVALID_VALUE;
	int low_tpt = IWL_INVALID_VALUE;
	int high_tpt = IWL_INVALID_VALUE;
Z
Zhu Yi 已提交
648 649 650 651
	u32 fail_count;
	s8 scale_action = 0;
	unsigned long flags;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
652 653
	u16 fc;
	u16 rate_mask = 0;
654
	s8 max_rate_idx = -1;
655
	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
656
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Z
Zhu Yi 已提交
657 658 659

	IWL_DEBUG_RATE("enter\n");

660 661 662
	if (sta)
		rate_mask = sta->supp_rates[sband->band];

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

679 680 681 682 683 684 685
	/* get user max rate if set */
	max_rate_idx = txrc->max_rate_idx;
	if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
		max_rate_idx += IWL_FIRST_OFDM_RATE;
	if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
		max_rate_idx = -1;

686
	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
687

T
Tomas Winkler 已提交
688
	if (sband->band == IEEE80211_BAND_5GHZ)
689
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
690

691
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
692
	    !rs_sta->ibss_sta_added) {
C
Christoph Hellwig 已提交
693
		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
694 695

		if (sta_id == IWL_INVALID_STATION) {
J
Johannes Berg 已提交
696 697
			IWL_DEBUG_RATE("LQ: ADD station %pm\n",
				       hdr->addr1);
C
Christoph Hellwig 已提交
698
			sta_id = iwl3945_add_station(priv,
Z
Zhu Yi 已提交
699 700 701
				    hdr->addr1, 0, CMD_ASYNC);
		}
		if (sta_id != IWL_INVALID_STATION)
702
			rs_sta->ibss_sta_added = 1;
Z
Zhu Yi 已提交
703 704
	}

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

707 708 709
	/* for recent assoc, choose best rate regarding
	 * to rssi value
	 */
710
	if (rs_sta->start_rate != IWL_RATE_INVALID) {
711 712 713
		if (rs_sta->start_rate < index &&
		   (rate_mask & (1 << rs_sta->start_rate)))
			index = rs_sta->start_rate;
714
		rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
715 716
	}

717 718 719 720 721 722
	/* force user max rate if set by user */
	if ((max_rate_idx != -1) && (max_rate_idx < index)) {
		if (rate_mask & (1 << max_rate_idx))
			index = max_rate_idx;
	}

723
	window = &(rs_sta->win[index]);
Z
Zhu Yi 已提交
724 725 726 727 728

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

	if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
729
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
730 731 732 733 734 735 736

		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,
737
			       rs_sta->expected_tpt ? "not " : "");
Z
Zhu Yi 已提交
738 739 740 741 742 743
		goto out;

	}

	current_tpt = window->average_tpt;

744
	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
T
Tomas Winkler 已提交
745
					     sband->band);
Z
Zhu Yi 已提交
746 747 748
	low = high_low & 0xff;
	high = (high_low >> 8) & 0xff;

749 750 751 752
	/* If user set max rate, dont allow higher than user constrain */
	if ((max_rate_idx != -1) && (max_rate_idx < high))
		high = IWL_RATE_INVALID;

Z
Zhu Yi 已提交
753
	if (low != IWL_RATE_INVALID)
754
		low_tpt = rs_sta->win[low].average_tpt;
Z
Zhu Yi 已提交
755 756

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

759
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
760 761 762 763 764 765

	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;
766 767
	} else if ((low_tpt == IWL_INVALID_VALUE) &&
		   (high_tpt == IWL_INVALID_VALUE))
Z
Zhu Yi 已提交
768
		scale_action = 1;
769 770
	else if ((low_tpt != IWL_INVALID_VALUE) &&
		 (high_tpt != IWL_INVALID_VALUE) &&
T
Tomas Winkler 已提交
771
		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
Z
Zhu Yi 已提交
772 773 774 775 776
		IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
			       "current_tpt [%d]\n",
			       low_tpt, high_tpt, current_tpt);
		scale_action = 0;
	} else {
777
		if (high_tpt != IWL_INVALID_VALUE) {
Z
Zhu Yi 已提交
778 779 780 781 782 783 784
			if (high_tpt > current_tpt)
				scale_action = 1;
			else {
				IWL_DEBUG_RATE
				    ("decrease rate because of high tpt\n");
				scale_action = -1;
			}
785
		} else if (low_tpt != IWL_INVALID_VALUE) {
Z
Zhu Yi 已提交
786 787 788 789 790 791 792 793 794
			if (low_tpt > current_tpt) {
				IWL_DEBUG_RATE
				    ("decrease rate because of low tpt\n");
				scale_action = -1;
			} else
				scale_action = 1;
		}
	}

795 796 797 798 799 800 801 802 803
	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 已提交
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
	}

	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:

828
	rs_sta->last_txrate_idx = index;
T
Tomas Winkler 已提交
829
	if (sband->band == IEEE80211_BAND_5GHZ)
830 831
		info->control.rates[0].idx = rs_sta->last_txrate_idx -
				IWL_FIRST_OFDM_RATE;
832
	else
833
		info->control.rates[0].idx = rs_sta->last_txrate_idx;
834

Z
Zhu Yi 已提交
835 836 837
	IWL_DEBUG_RATE("leave: %d\n", index);
}

A
Abbas, Mohamed 已提交
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
#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));
859
	for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
A
Abbas, Mohamed 已提交
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
		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 已提交
892 893 894 895 896 897 898 899 900 901
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 已提交
902 903 904 905 906
#ifdef CONFIG_MAC80211_DEBUGFS
	.add_sta_debugfs = iwl3945_add_debugfs,
	.remove_sta_debugfs = iwl3945_remove_debugfs,
#endif

Z
Zhu Yi 已提交
907 908
};

C
Christoph Hellwig 已提交
909
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
Z
Zhu Yi 已提交
910
{
911
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
912 913
	s32 rssi = 0;
	unsigned long flags;
914
	struct iwl3945_rs_sta *rs_sta;
915 916
	struct ieee80211_sta *sta;
	struct iwl3945_sta_priv *psta;
Z
Zhu Yi 已提交
917 918 919

	IWL_DEBUG_RATE("enter\n");

920 921
	rcu_read_lock();

922
	sta = ieee80211_find_sta(hw, priv->stations_39[sta_id].sta.sta.addr);
923
	if (!sta) {
924
		rcu_read_unlock();
Z
Zhu Yi 已提交
925 926 927
		return;
	}

928
	psta = (void *) sta->drv_priv;
929
	rs_sta = psta->rs_sta;
Z
Zhu Yi 已提交
930

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

933
	rs_sta->tgg = 0;
934 935 936
	switch (priv->band) {
	case IEEE80211_BAND_2GHZ:
		/* TODO: this always does G, not a regression */
937
		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
938 939
			rs_sta->tgg = 1;
			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
Z
Zhu Yi 已提交
940
		} else
941
			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
Z
Zhu Yi 已提交
942 943
		break;

944
	case IEEE80211_BAND_5GHZ:
945
		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
Z
Zhu Yi 已提交
946
		break;
947 948
	case IEEE80211_NUM_BANDS:
		BUG();
Z
Zhu Yi 已提交
949 950 951
		break;
	}

952
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
953 954 955 956 957 958 959

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

960
	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
Z
Zhu Yi 已提交
961 962

	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
963 964
		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
		       iwl3945_rates[rs_sta->start_rate].plcp);
965
	rcu_read_unlock();
Z
Zhu Yi 已提交
966 967
}

968
int iwl3945_rate_control_register(void)
Z
Zhu Yi 已提交
969
{
970
	return ieee80211_rate_control_register(&rs_ops);
Z
Zhu Yi 已提交
971 972
}

973
void iwl3945_rate_control_unregister(void)
Z
Zhu Yi 已提交
974 975 976 977 978
{
	ieee80211_rate_control_unregister(&rs_ops);
}