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

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

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

#include <linux/workqueue.h>

J
Johannes Berg 已提交
39
#include "../net/mac80211/rate.h"
Z
Zhu Yi 已提交
40

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

#define RS_NAME "iwl-3945-rs"

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

54
struct iwl3945_rs_sta {
Z
Zhu Yi 已提交
55 56 57 58 59 60 61 62 63 64 65 66
	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 已提交
67
	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
68 69 70

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return unflushed;
}

#define IWL_RATE_FLUSH_MAX              5000	/* msec */
#define IWL_RATE_FLUSH_MIN              50	/* msec */

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

	IWL_DEBUG_RATE("enter\n");

218
	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
Z
Zhu Yi 已提交
219

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

222
	rs_sta->flush_pending = 0;
Z
Zhu Yi 已提交
223 224

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

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

	if (unflushed) {
		duration =
231 232
		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
/*              duration = jiffies_to_msecs(rs_sta->flush_time); */
Z
Zhu Yi 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

		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) {
			duration = IWL_RATE_FLUSH_MAX / pps;
			if (duration < IWL_RATE_FLUSH_MIN)
				duration = IWL_RATE_FLUSH_MIN;
		} else
			duration = IWL_RATE_FLUSH_MAX;

250
		rs_sta->flush_time = msecs_to_jiffies(duration);
Z
Zhu Yi 已提交
251 252 253 254

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

255 256
		mod_timer(&rs_sta->rate_scale_flush, jiffies +
			  rs_sta->flush_time);
Z
Zhu Yi 已提交
257

258
		rs_sta->last_partial_flush = jiffies;
Z
Zhu Yi 已提交
259 260 261 262 263
	}

	/* If there weren't any unflushed entries, we don't schedule the timer
	 * to run again */

264
	rs_sta->last_flush = jiffies;
Z
Zhu Yi 已提交
265

266
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
267 268 269 270 271

	IWL_DEBUG_RATE("leave\n");
}

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

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

	while (retries--) {
290
		spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317

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

318
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
319 320 321 322 323 324
	}
}

static void rs_rate_init(void *priv_rate, void *priv_sta,
			 struct ieee80211_local *local, struct sta_info *sta)
{
325
	struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv;
Z
Zhu Yi 已提交
326 327 328 329 330 331 332 333 334 335
	int i;

	IWL_DEBUG_RATE("enter\n");

	/* TODO: what is a good starting rate for STA? About middle? Maybe not
	 * the lowest or the highest rate.. Could consider using RSSI from
	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
	 * after assoc.. */

	for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
J
Johannes Berg 已提交
336
		if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) {
337
			rs_sta->last_txrate_idx = i;
Z
Zhu Yi 已提交
338 339 340 341
			break;
		}
	}

342 343
	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
	if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
344
		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
345

Z
Zhu Yi 已提交
346 347 348 349 350 351 352 353
	IWL_DEBUG_RATE("leave\n");
}

static void *rs_alloc(struct ieee80211_local *local)
{
	return local->hw.priv;
}

354
/* rate scale requires free function to be implemented */
Z
Zhu Yi 已提交
355 356 357 358 359 360 361 362 363 364 365 366
static void rs_free(void *priv)
{
	return;
}
static void rs_clear(void *priv)
{
	return;
}


static void *rs_alloc_sta(void *priv, gfp_t gfp)
{
367
	struct iwl3945_rs_sta *rs_sta;
Z
Zhu Yi 已提交
368 369 370 371
	int i;

	IWL_DEBUG_RATE("enter\n");

372 373
	rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
	if (!rs_sta) {
Z
Zhu Yi 已提交
374 375 376 377
		IWL_DEBUG_RATE("leave: ENOMEM\n");
		return NULL;
	}

378
	spin_lock_init(&rs_sta->lock);
Z
Zhu Yi 已提交
379

380
	rs_sta->start_rate = IWL_RATE_INVALID;
Z
Zhu Yi 已提交
381 382

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

385 386 387 388 389
	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 已提交
390

391 392 393
	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 已提交
394 395

	for (i = 0; i < IWL_RATE_COUNT; i++)
396
		iwl3945_clear_window(&rs_sta->win[i]);
Z
Zhu Yi 已提交
397 398 399

	IWL_DEBUG_RATE("leave\n");

400
	return rs_sta;
Z
Zhu Yi 已提交
401 402 403 404
}

static void rs_free_sta(void *priv, void *priv_sta)
{
405
	struct iwl3945_rs_sta *rs_sta = priv_sta;
Z
Zhu Yi 已提交
406 407

	IWL_DEBUG_RATE("enter\n");
408 409
	del_timer_sync(&rs_sta->rate_scale_flush);
	kfree(rs_sta);
Z
Zhu Yi 已提交
410 411 412
	IWL_DEBUG_RATE("leave\n");
}

413 414 415 416 417 418

/*
 * get ieee prev rate from rate scale table.
 * for A and B mode we need to overright prev
 * value
 */
C
Christoph Hellwig 已提交
419
static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
420
{
C
Christoph Hellwig 已提交
421
	int next_rate = iwl3945_get_prev_ieee_rate(rate);
422

423 424
	switch (priv->band) {
	case IEEE80211_BAND_5GHZ:
425 426 427 428 429
		if (rate == IWL_RATE_12M_INDEX)
			next_rate = IWL_RATE_9M_INDEX;
		else if (rate == IWL_RATE_6M_INDEX)
			next_rate = IWL_RATE_6M_INDEX;
		break;
430
/* XXX cannot be invoked in current mac80211 so not a regression
431 432 433 434
	case MODE_IEEE80211B:
		if (rate == IWL_RATE_11M_INDEX_TABLE)
			next_rate = IWL_RATE_5M_INDEX_TABLE;
		break;
435
 */
436 437 438 439 440 441
	default:
		break;
	}

	return next_rate;
}
Z
Zhu Yi 已提交
442 443 444
/**
 * rs_tx_status - Update rate control values based on Tx results
 *
C
Christoph Hellwig 已提交
445
 * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by
Z
Zhu Yi 已提交
446 447 448 449
 * the hardware for each rate.
 */
static void rs_tx_status(void *priv_rate,
			 struct net_device *dev,
450
			 struct sk_buff *skb)
Z
Zhu Yi 已提交
451 452 453 454 455 456
{
	u8 retries, current_count;
	int scale_rate_index, first_index, last_index;
	unsigned long flags;
	struct sta_info *sta;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
C
Christoph Hellwig 已提交
457
	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
Z
Zhu Yi 已提交
458
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
459
	struct iwl3945_rs_sta *rs_sta;
460
	struct ieee80211_supported_band *sband;
461
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
462

T
Tomas Winkler 已提交
463 464
	IWL_DEBUG_RATE("enter\n");

465
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
Z
Zhu Yi 已提交
466 467


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

475 476
	rcu_read_lock();

Z
Zhu Yi 已提交
477 478
	sta = sta_info_get(local, hdr->addr1);
	if (!sta || !sta->rate_ctrl_priv) {
479
		rcu_read_unlock();
Z
Zhu Yi 已提交
480 481 482 483
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
		return;
	}

484
	rs_sta = (void *)sta->rate_ctrl_priv;
Z
Zhu Yi 已提交
485

486
	rs_sta->tx_packets++;
Z
Zhu Yi 已提交
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

	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)
	 */
	while (retries > 0) {
		if (retries < priv->retry_rate) {
			current_count = retries;
			last_index = scale_rate_index;
		} else {
			current_count = priv->retry_rate;
507 508
			last_index = rs_adjust_next_rate(priv,
							 scale_rate_index);
Z
Zhu Yi 已提交
509 510 511 512
		}

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

		retries -= current_count;

		if (retries)
			scale_rate_index =
523
			    rs_adjust_next_rate(priv, scale_rate_index);
Z
Zhu Yi 已提交
524 525
	}

526

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

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

541 542 543
	if (!rs_sta->flush_pending &&
	    time_after(jiffies, rs_sta->last_partial_flush +
		       rs_sta->flush_time)) {
Z
Zhu Yi 已提交
544

545 546 547
		rs_sta->flush_pending = 1;
		mod_timer(&rs_sta->rate_scale_flush,
			  jiffies + rs_sta->flush_time);
Z
Zhu Yi 已提交
548 549
	}

550
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
551

552
	rcu_read_unlock();
Z
Zhu Yi 已提交
553 554 555 556 557 558

	IWL_DEBUG_RATE("leave\n");

	return;
}

559
static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
560
				 u8 index, u16 rate_mask, enum ieee80211_band band)
Z
Zhu Yi 已提交
561 562 563 564
{
	u8 high = IWL_RATE_INVALID;
	u8 low = IWL_RATE_INVALID;

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

	IWL_DEBUG_RATE("enter\n");

663 664
	rcu_read_lock();

Z
Zhu Yi 已提交
665
	sta = sta_info_get(local, hdr->addr1);
666 667 668 669 670 671 672

	/* 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) ||
	    !sta || !sta->rate_ctrl_priv) {
Z
Zhu Yi 已提交
673
		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
674
		sel->rate_idx = rate_lowest_index(local, sband, sta);
675
		rcu_read_unlock();
676
		return;
Z
Zhu Yi 已提交
677 678
	}

679 680
	rs_sta = (void *)sta->rate_ctrl_priv;

J
Johannes Berg 已提交
681
	rate_mask = sta->sta.supp_rates[sband->band];
682
	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
683

T
Tomas Winkler 已提交
684
	if (sband->band == IEEE80211_BAND_5GHZ)
685
		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
686

687
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
688
	    !rs_sta->ibss_sta_added) {
C
Christoph Hellwig 已提交
689
		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
690 691

		if (sta_id == IWL_INVALID_STATION) {
692 693
			IWL_DEBUG_RATE("LQ: ADD station %s\n",
				       print_mac(mac, hdr->addr1));
C
Christoph Hellwig 已提交
694
			sta_id = iwl3945_add_station(priv,
Z
Zhu Yi 已提交
695 696 697
				    hdr->addr1, 0, CMD_ASYNC);
		}
		if (sta_id != IWL_INVALID_STATION)
698
			rs_sta->ibss_sta_added = 1;
Z
Zhu Yi 已提交
699 700
	}

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

703 704 705
	if (rs_sta->start_rate != IWL_RATE_INVALID) {
		index = rs_sta->start_rate;
		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))) {
T
Tomas Winkler 已提交
714
		window->average_tpt = IWL_INV_TPT;
715
		spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
716 717 718 719 720 721 722

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

	}

	window->average_tpt = ((window->success_ratio *
729
				rs_sta->expected_tpt[index] + 64) / 128);
Z
Zhu Yi 已提交
730 731
	current_tpt = window->average_tpt;

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

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

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

743
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
744 745 746 747 748 749

	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 已提交
750
	} else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
Z
Zhu Yi 已提交
751
		scale_action = 1;
T
Tomas Winkler 已提交
752 753
	else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
Z
Zhu Yi 已提交
754 755 756 757 758
		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 已提交
759
		if (high_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
760 761 762 763 764 765 766
			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 已提交
767
		} else if (low_tpt != IWL_INV_TPT) {
Z
Zhu Yi 已提交
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
			if (low_tpt > current_tpt) {
				IWL_DEBUG_RATE
				    ("decrease rate because of low tpt\n");
				scale_action = -1;
			} else
				scale_action = 1;
		}
	}

	if ((window->success_ratio > IWL_RATE_HIGH_TH) ||
	    (current_tpt > window->average_tpt)) {
		IWL_DEBUG_RATE("No action -- success_ratio [%d] > HIGH_TH or "
			       "current_tpt [%d] > average_tpt [%d]\n",
			       window->success_ratio,
			       current_tpt, window->average_tpt);
		scale_action = 0;
	}

	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:

808
	rs_sta->last_txrate_idx = index;
T
Tomas Winkler 已提交
809
	if (sband->band == IEEE80211_BAND_5GHZ)
810
		sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
811
	else
812
		sel->rate_idx = rs_sta->last_txrate_idx;
813

814
	rcu_read_unlock();
Z
Zhu Yi 已提交
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831

	IWL_DEBUG_RATE("leave: %d\n", index);
}

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,
	.clear = rs_clear,
	.alloc = rs_alloc,
	.free = rs_free,
	.alloc_sta = rs_alloc_sta,
	.free_sta = rs_free_sta,
};

C
Christoph Hellwig 已提交
832
int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
Z
Zhu Yi 已提交
833 834
{
	struct ieee80211_local *local = hw_to_local(hw);
C
Christoph Hellwig 已提交
835
	struct iwl3945_priv *priv = hw->priv;
836
	struct iwl3945_rs_sta *rs_sta;
Z
Zhu Yi 已提交
837 838 839 840 841 842 843
	struct sta_info *sta;
	unsigned long flags;
	int count = 0, i;
	u32 samples = 0, success = 0, good = 0;
	unsigned long now = jiffies;
	u32 max_time = 0;

844 845
	rcu_read_lock();

Z
Zhu Yi 已提交
846 847
	sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
	if (!sta || !sta->rate_ctrl_priv) {
848
		if (sta)
Z
Zhu Yi 已提交
849
			IWL_DEBUG_RATE("leave - no private rate data!\n");
850
		else
Z
Zhu Yi 已提交
851
			IWL_DEBUG_RATE("leave - no station!\n");
852
		rcu_read_unlock();
Z
Zhu Yi 已提交
853 854 855
		return sprintf(buf, "station %d not found\n", sta_id);
	}

856 857
	rs_sta = (void *)sta->rate_ctrl_priv;
	spin_lock_irqsave(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
858 859 860 861 862 863
	i = IWL_RATE_54M_INDEX;
	while (1) {
		u64 mask;
		int j;

		count +=
C
Christoph Hellwig 已提交
864
		    sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2);
Z
Zhu Yi 已提交
865 866 867 868

		mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1));
		for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1)
			buf[count++] =
869
			    (rs_sta->win[i].data & mask) ? '1' : '0';
Z
Zhu Yi 已提交
870

871 872 873 874
		samples += rs_sta->win[i].counter;
		good += rs_sta->win[i].success_counter;
		success += rs_sta->win[i].success_counter *
						iwl3945_rates[i].ieee;
Z
Zhu Yi 已提交
875

876
		if (rs_sta->win[i].stamp) {
Z
Zhu Yi 已提交
877
			int delta =
878
			    jiffies_to_msecs(now - rs_sta->win[i].stamp);
Z
Zhu Yi 已提交
879 880 881 882 883 884 885 886

			if (delta > max_time)
				max_time = delta;

			count += sprintf(&buf[count], "%5dms\n", delta);
		} else
			buf[count++] = '\n';

C
Christoph Hellwig 已提交
887
		j = iwl3945_get_prev_ieee_rate(i);
Z
Zhu Yi 已提交
888 889 890 891
		if (j == i)
			break;
		i = j;
	}
892
	spin_unlock_irqrestore(&rs_sta->lock, flags);
893
	rcu_read_unlock();
Z
Zhu Yi 已提交
894 895 896 897

	/* Display the average rate of all samples taken.
	 *
	 * NOTE:  We multiple # of samples by 2 since the IEEE measurement
C
Christoph Hellwig 已提交
898
	 * added from iwl3945_rates is actually 2X the rate */
Z
Zhu Yi 已提交
899 900 901 902 903 904 905 906 907 908 909 910 911
	if (samples)
		count += sprintf(
			&buf[count],
			"\nAverage rate is %3d.%02dMbs over last %4dms\n"
			"%3d%% success (%d good packets over %d tries)\n",
			success / (2 * samples), (success * 5 / samples) % 10,
			max_time, good * 100 / samples, good, samples);
	else
		count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n");

	return count;
}

C
Christoph Hellwig 已提交
912
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
Z
Zhu Yi 已提交
913
{
C
Christoph Hellwig 已提交
914
	struct iwl3945_priv *priv = hw->priv;
Z
Zhu Yi 已提交
915 916 917
	s32 rssi = 0;
	unsigned long flags;
	struct ieee80211_local *local = hw_to_local(hw);
918
	struct iwl3945_rs_sta *rs_sta;
Z
Zhu Yi 已提交
919 920 921 922 923 924 925 926 927 928 929
	struct sta_info *sta;

	IWL_DEBUG_RATE("enter\n");

	if (!local->rate_ctrl->ops->name ||
	    strcmp(local->rate_ctrl->ops->name, RS_NAME)) {
		IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n");
		IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n");
		return;
	}

930 931
	rcu_read_lock();

Z
Zhu Yi 已提交
932 933 934
	sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
	if (!sta || !sta->rate_ctrl_priv) {
		IWL_DEBUG_RATE("leave - no private rate data!\n");
935
		rcu_read_unlock();
Z
Zhu Yi 已提交
936 937 938
		return;
	}

939
	rs_sta = (void *)sta->rate_ctrl_priv;
Z
Zhu Yi 已提交
940

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

943
	rs_sta->tgg = 0;
944 945 946
	switch (priv->band) {
	case IEEE80211_BAND_2GHZ:
		/* TODO: this always does G, not a regression */
Z
Zhu Yi 已提交
947
		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
948 949
			rs_sta->tgg = 1;
			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
Z
Zhu Yi 已提交
950
		} else
951
			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
Z
Zhu Yi 已提交
952 953
		break;

954
	case IEEE80211_BAND_5GHZ:
955
		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
Z
Zhu Yi 已提交
956
		break;
957 958
	case IEEE80211_NUM_BANDS:
		BUG();
Z
Zhu Yi 已提交
959 960 961
		break;
	}

962
	rcu_read_unlock();
963
	spin_unlock_irqrestore(&rs_sta->lock, flags);
Z
Zhu Yi 已提交
964 965 966 967 968 969 970

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

971
	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
Z
Zhu Yi 已提交
972 973

	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
974 975
		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
		       iwl3945_rates[rs_sta->start_rate].plcp);
Z
Zhu Yi 已提交
976 977
}

978
int iwl3945_rate_control_register(void)
Z
Zhu Yi 已提交
979
{
980
	return ieee80211_rate_control_register(&rs_ops);
Z
Zhu Yi 已提交
981 982
}

983
void iwl3945_rate_control_unregister(void)
Z
Zhu Yi 已提交
984 985 986 987 988
{
	ieee80211_rate_control_unregister(&rs_ops);
}