aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/pm.c
Commit message (Expand)AuthorAge
* mac80211: assure we also cancel deferred scan requestStanislaw Gruszka2010-10-06
* mac80211: avoid transmitting delBA to old APJohannes Berg2010-10-06
* mac80211: only cancel software-based scans on suspendJohn W. Linville2010-09-01
* mac80211: use common work structJohannes Berg2010-06-14
* mac80211: simplify station/aggregation codeJohannes Berg2010-06-14
* mac80211: rename WLAN_STA_SUSPEND to WLAN_STA_BLOCK_BAJohannes Berg2010-04-07
* mac80211: allow station add/remove to sleepJohannes Berg2010-02-08
* mac80211: remove struct ieee80211_if_init_confJohannes Berg2009-12-28
* mac80211: add ieee80211_sdata_runningJohannes Berg2009-12-28
* mac80211: trace interface nameJohannes Berg2009-12-21
* mac80211: reduce reliance on netdevJohannes Berg2009-12-21
* mac80211: fix configure_filter invocation after stopJohannes Berg2009-08-28
* mac80211: redefine usage of the mac80211 workqueueLuis R. Rodriguez2009-08-04
* mac80211: disable beacons before removing the associated interfaceBob Copeland2009-08-04
* mac80211: fix suspendJohannes Berg2009-07-29
* mac80211: cancel/restart all timers across suspend/resumeJohannes Berg2009-05-20
* mac80211: add driver ops wrappersJohannes Berg2009-05-06
* mac80211: add hardware restart functionJohannes Berg2009-04-22
* mac80211: re-upload keys only after telling driver about associationJohannes Berg2009-04-22
* mac80211: resume properly, add suspend/resume testJohannes Berg2009-03-27
* mac80211: Tear down aggregation sessions for suspend/resumeSujith2009-03-27
* mac80211: acquire sta_lock for station suspend/resumeJohannes Berg2009-03-27
* mac80211: stop queues across suspend/resumeJohannes Berg2009-03-27
* mac80211: flush workqueue a second time in suspend()Bob Copeland2009-01-29
* mac80211: add suspend/resume callbacksBob Copeland2009-01-29
='n237' href='#n237'>237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 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 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
/*******************************************************************************

  
  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
  
  This program is free software; you can redistribute it and/or modify it 
  under the terms of the GNU General Public License as published by the Free 
  Software Foundation; either version 2 of the License, or (at your option) 
  any later version.
  
  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., 59 
  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  
  The full GNU General Public License is included in this distribution in the
  file called LICENSE.
  
  Contact Information:
  Linux NICS <linux.nics@intel.com>
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497

*******************************************************************************/

#include "ixgb.h"

/* This is the only thing that needs to be changed to adjust the
 * maximum number of ports that the driver can manage.
 */

#define IXGB_MAX_NIC 8

#define OPTION_UNSET	-1
#define OPTION_DISABLED 0
#define OPTION_ENABLED  1

/* All parameters are treated the same, as an integer array of values.
 * This macro just reduces the need to repeat the same declaration code
 * over and over (plus this helps to avoid typo bugs).
 */

#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
#define IXGB_PARAM(X, desc) \
	static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \
	static int num_##X = 0; \
	module_param_array_named(X, X, int, &num_##X, 0); \
	MODULE_PARM_DESC(X, desc);

/* Transmit Descriptor Count
 *
 * Valid Range: 64-4096
 *
 * Default Value: 256
 */

IXGB_PARAM(TxDescriptors, "Number of transmit descriptors");

/* Receive Descriptor Count
 *
 * Valid Range: 64-4096
 *
 * Default Value: 1024
 */

IXGB_PARAM(RxDescriptors, "Number of receive descriptors");

/* User Specified Flow Control Override
 *
 * Valid Range: 0-3
 *  - 0 - No Flow Control
 *  - 1 - Rx only, respond to PAUSE frames but do not generate them
 *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
 *  - 3 - Full Flow Control Support
 *
 * Default Value: Read flow control settings from the EEPROM
 */

IXGB_PARAM(FlowControl, "Flow Control setting");

/* XsumRX - Receive Checksum Offload Enable/Disable
 *
 * Valid Range: 0, 1
 *  - 0 - disables all checksum offload
 *  - 1 - enables receive IP/TCP/UDP checksum offload
 *        on 82597 based NICs
 *
 * Default Value: 1
 */

IXGB_PARAM(XsumRX, "Disable or enable Receive Checksum offload");

/* Transmit Interrupt Delay in units of 0.8192 microseconds
 *
 * Valid Range: 0-65535
 *
 * Default Value: 32
 */

IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay");

/* Receive Interrupt Delay in units of 0.8192 microseconds
 *
 * Valid Range: 0-65535
 *
 * Default Value: 72
 */

IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay");

/* Receive Flow control high threshold (when we send a pause frame)
 * (FCRTH)
 *
 * Valid Range: 1,536 - 262,136 (0x600 - 0x3FFF8, 8 byte granularity)
 *
 * Default Value: 196,608 (0x30000)
 */

IXGB_PARAM(RxFCHighThresh, "Receive Flow Control High Threshold");

/* Receive Flow control low threshold (when we send a resume frame)
 * (FCRTL)
 *
 * Valid Range: 64 - 262,136 (0x40 - 0x3FFF8, 8 byte granularity)
 *              must be less than high threshold by at least 8 bytes
 *
 * Default Value:  163,840 (0x28000)
 */

IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold");

/* Flow control request timeout (how long to pause the link partner's tx)
 * (PAP 15:0)
 *
 * Valid Range: 1 - 65535 
 *
 * Default Value:  256 (0x100)
 */

IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");

/* Interrupt Delay Enable
 *
 * Valid Range: 0, 1
 *
 *  - 0 - disables transmit interrupt delay
 *  - 1 - enables transmmit interrupt delay
 *
 * Default Value: 1
 */

IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");


#define DEFAULT_TIDV	   		     32
#define MAX_TIDV			 0xFFFF
#define MIN_TIDV			      0

#define DEFAULT_RDTR		   	     72
#define MAX_RDTR			 0xFFFF
#define MIN_RDTR			      0

#define XSUMRX_DEFAULT		 OPTION_ENABLED

#define FLOW_CONTROL_FULL	   ixgb_fc_full
#define FLOW_CONTROL_DEFAULT  FLOW_CONTROL_FULL
#define DEFAULT_FCRTL	  		0x28000
#define DEFAULT_FCRTH			0x30000
#define MIN_FCRTL			      0
#define MAX_FCRTL			0x3FFE8
#define MIN_FCRTH			      8
#define MAX_FCRTH			0x3FFF0

#define DEFAULT_FCPAUSE		  	0x100	/* this may be too long */
#define MIN_FCPAUSE			      1
#define MAX_FCPAUSE			 0xffff

struct ixgb_option {
	enum { enable_option, range_option, list_option } type;
	char *name;
	char *err;
	int def;
	union {
		struct {	/* range_option info */
			int min;
			int max;
		} r;
		struct {	/* list_option info */
			int nr;
			struct ixgb_opt_list {
				int i;
				char *str;
			} *p;
		} l;
	} arg;
};

static int __devinit
ixgb_validate_option(int *value, struct ixgb_option *opt)
{
	if(*value == OPTION_UNSET) {
		*value = opt->def;
		return 0;
	}

	switch (opt->type) {
	case enable_option:
		switch (*value) {
		case OPTION_ENABLED:
			printk(KERN_INFO "%s Enabled\n", opt->name);
			return 0;
		case OPTION_DISABLED:
			printk(KERN_INFO "%s Disabled\n", opt->name);
			return 0;
		}
		break;
	case range_option:
		if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
			printk(KERN_INFO "%s set to %i\n", opt->name, *value);
			return 0;
		}
		break;
	case list_option: {
		int i;
		struct ixgb_opt_list *ent;

		for(i = 0; i < opt->arg.l.nr; i++) {
			ent = &opt->arg.l.p[i];
			if(*value == ent->i) {
				if(ent->str[0] != '\0')
					printk(KERN_INFO "%s\n", ent->str);
				return 0;
			}
		}
	}
		break;
	default:
		BUG();
	}

	printk(KERN_INFO "Invalid %s specified (%i) %s\n",
		   opt->name, *value, opt->err);
	*value = opt->def;
	return -1;
}

#define LIST_LEN(l) (sizeof(l) / sizeof(l[0]))

/**
 * ixgb_check_options - Range Checking for Command Line Parameters
 * @adapter: board private structure
 *
 * This routine checks all command line parameters for valid user
 * input.  If an invalid value is given, or if no user specified
 * value exists, a default value is used.  The final value is stored
 * in a variable in the adapter structure.
 **/

void __devinit
ixgb_check_options(struct ixgb_adapter *adapter)
{
	int bd = adapter->bd_number;
	if(bd >= IXGB_MAX_NIC) {
		printk(KERN_NOTICE
			   "Warning: no configuration for board #%i\n", bd);
		printk(KERN_NOTICE "Using defaults for all values\n");
	}

	{ /* Transmit Descriptor Count */
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Transmit Descriptors",
			.err  = "using default of " __MODULE_STRING(DEFAULT_TXD),
			.def  = DEFAULT_TXD,
			.arg  = { .r = { .min = MIN_TXD,
					 .max = MAX_TXD}}
		};
		struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;

		if(num_TxDescriptors > bd) {
			tx_ring->count = TxDescriptors[bd];
			ixgb_validate_option(&tx_ring->count, &opt);
		} else {
			tx_ring->count = opt.def;
		}
		IXGB_ROUNDUP(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
	}
	{ /* Receive Descriptor Count */
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Receive Descriptors",
			.err  = "using default of " __MODULE_STRING(DEFAULT_RXD),
			.def  = DEFAULT_RXD,
			.arg  = { .r = { .min = MIN_RXD,
					 .max = MAX_RXD}}
		};
		struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;

		if(num_RxDescriptors > bd) {
			rx_ring->count = RxDescriptors[bd];
			ixgb_validate_option(&rx_ring->count, &opt);
		} else {
			rx_ring->count = opt.def;
		}
		IXGB_ROUNDUP(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
	}
	{ /* Receive Checksum Offload Enable */
		struct ixgb_option opt = {
			.type = enable_option,
			.name = "Receive Checksum Offload",
			.err  = "defaulting to Enabled",
			.def  = OPTION_ENABLED
		};

		if(num_XsumRX > bd) {
			int rx_csum = XsumRX[bd];
			ixgb_validate_option(&rx_csum, &opt);
			adapter->rx_csum = rx_csum;
		} else {
			adapter->rx_csum = opt.def;
		}
	}
	{ /* Flow Control */

		struct ixgb_opt_list fc_list[] =
			{{ ixgb_fc_none,	"Flow Control Disabled" },
			 { ixgb_fc_rx_pause,"Flow Control Receive Only" },
			 { ixgb_fc_tx_pause,"Flow Control Transmit Only" },
			 { ixgb_fc_full,	"Flow Control Enabled" },
			 { ixgb_fc_default, "Flow Control Hardware Default" }};

		struct ixgb_option opt = {
			.type = list_option,
			.name = "Flow Control",
			.err  = "reading default settings from EEPROM",
			.def  = ixgb_fc_full,
			.arg  = { .l = { .nr = LIST_LEN(fc_list),
					 .p = fc_list }}
		};

		if(num_FlowControl > bd) {
			int fc = FlowControl[bd];
			ixgb_validate_option(&fc, &opt);
			adapter->hw.fc.type = fc;
		} else {
			adapter->hw.fc.type = opt.def;
		}
	}
	{ /* Receive Flow Control High Threshold */
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Rx Flow Control High Threshold",
			.err  = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
			.def  = DEFAULT_FCRTH,
			.arg  = { .r = { .min = MIN_FCRTH,
					 .max = MAX_FCRTH}}
		};

		if(num_RxFCHighThresh > bd) {
			adapter->hw.fc.high_water = RxFCHighThresh[bd];
			ixgb_validate_option(&adapter->hw.fc.high_water, &opt);
		} else {
			adapter->hw.fc.high_water = opt.def;
		}
		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
			printk (KERN_INFO 
				"Ignoring RxFCHighThresh when no RxFC\n");
	}
	{ /* Receive Flow Control Low Threshold */
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Rx Flow Control Low Threshold",
			.err  = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
			.def  = DEFAULT_FCRTL,
			.arg  = { .r = { .min = MIN_FCRTL,
					 .max = MAX_FCRTL}}
		};

		if(num_RxFCLowThresh > bd) {
			adapter->hw.fc.low_water = RxFCLowThresh[bd];
			ixgb_validate_option(&adapter->hw.fc.low_water, &opt);
		} else {
			adapter->hw.fc.low_water = opt.def;
		}
		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
			printk (KERN_INFO 
				"Ignoring RxFCLowThresh when no RxFC\n");
	}
	{ /* Flow Control Pause Time Request*/
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Flow Control Pause Time Request",
			.err  = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
			.def  = DEFAULT_FCPAUSE,
			.arg = { .r = { .min = MIN_FCPAUSE,
					.max = MAX_FCPAUSE}}
		};

		if(num_FCReqTimeout > bd) {
			int pause_time = FCReqTimeout[bd];
			ixgb_validate_option(&pause_time, &opt);
			adapter->hw.fc.pause_time = pause_time;
		} else {
			adapter->hw.fc.pause_time = opt.def;
		}
		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
			printk (KERN_INFO 
				"Ignoring FCReqTimeout when no RxFC\n");
	}
	/* high low and spacing check for rx flow control thresholds */
	if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
		/* high must be greater than low */
		if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
			/* set defaults */
			printk (KERN_INFO 
				"RxFCHighThresh must be >= (RxFCLowThresh + 8), "
				"Using Defaults\n");
			adapter->hw.fc.high_water = DEFAULT_FCRTH;
			adapter->hw.fc.low_water  = DEFAULT_FCRTL;
		}
	}
	{ /* Receive Interrupt Delay */
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Receive Interrupt Delay",
			.err  = "using default of " __MODULE_STRING(DEFAULT_RDTR),
			.def  = DEFAULT_RDTR,
			.arg  = { .r = { .min = MIN_RDTR,
					 .max = MAX_RDTR}}
		};

		if(num_RxIntDelay > bd) {
			adapter->rx_int_delay = RxIntDelay[bd];
			ixgb_validate_option(&adapter->rx_int_delay, &opt);
		} else {
			adapter->rx_int_delay = opt.def;
		}
	}
	{ /* Transmit Interrupt Delay */
		struct ixgb_option opt = {
			.type = range_option,
			.name = "Transmit Interrupt Delay",
			.err  = "using default of " __MODULE_STRING(DEFAULT_TIDV),
			.def  = DEFAULT_TIDV,
			.arg  = { .r = { .min = MIN_TIDV,
					 .max = MAX_TIDV}}
		};

		if(num_TxIntDelay > bd) {
			adapter->tx_int_delay = TxIntDelay[bd];
			ixgb_validate_option(&adapter->tx_int_delay, &opt);
		} else {
			adapter->tx_int_delay = opt.def;
		}
	}

	{ /* Transmit Interrupt Delay Enable */
		struct ixgb_option opt = {
			.type = enable_option,
			.name = "Tx Interrupt Delay Enable",
			.err  = "defaulting to Enabled",
			.def  = OPTION_ENABLED
		};

		if(num_IntDelayEnable > bd) {
			int ide = IntDelayEnable[bd];
			ixgb_validate_option(&ide, &opt);
			adapter->tx_int_delay_enable = ide;
		} else {
			adapter->tx_int_delay_enable = opt.def;
		}
	}
}