18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
58c2ecf20Sopenharmony_ci#include <linux/module.h>
68c2ecf20Sopenharmony_ci#include <linux/pci.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "e1000.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/* This is the only thing that needs to be changed to adjust the
118c2ecf20Sopenharmony_ci * maximum number of ports that the driver can manage.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci#define E1000_MAX_NIC 32
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define OPTION_UNSET   -1
168c2ecf20Sopenharmony_ci#define OPTION_DISABLED 0
178c2ecf20Sopenharmony_ci#define OPTION_ENABLED  1
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define COPYBREAK_DEFAULT 256
208c2ecf20Sopenharmony_ciunsigned int copybreak = COPYBREAK_DEFAULT;
218c2ecf20Sopenharmony_cimodule_param(copybreak, uint, 0644);
228c2ecf20Sopenharmony_ciMODULE_PARM_DESC(copybreak,
238c2ecf20Sopenharmony_ci		 "Maximum size of packet that is copied to a new buffer on receive");
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* All parameters are treated the same, as an integer array of values.
268c2ecf20Sopenharmony_ci * This macro just reduces the need to repeat the same declaration code
278c2ecf20Sopenharmony_ci * over and over (plus this helps to avoid typo bugs).
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_ci#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
308c2ecf20Sopenharmony_ci#define E1000_PARAM(X, desc)					\
318c2ecf20Sopenharmony_ci	static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT;	\
328c2ecf20Sopenharmony_ci	static unsigned int num_##X;				\
338c2ecf20Sopenharmony_ci	module_param_array_named(X, X, int, &num_##X, 0);	\
348c2ecf20Sopenharmony_ci	MODULE_PARM_DESC(X, desc);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* Transmit Interrupt Delay in units of 1.024 microseconds
378c2ecf20Sopenharmony_ci * Tx interrupt delay needs to typically be set to something non-zero
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci * Valid Range: 0-65535
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ciE1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
428c2ecf20Sopenharmony_ci#define DEFAULT_TIDV 8
438c2ecf20Sopenharmony_ci#define MAX_TXDELAY 0xFFFF
448c2ecf20Sopenharmony_ci#define MIN_TXDELAY 0
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * Valid Range: 0-65535
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_ciE1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
518c2ecf20Sopenharmony_ci#define DEFAULT_TADV 32
528c2ecf20Sopenharmony_ci#define MAX_TXABSDELAY 0xFFFF
538c2ecf20Sopenharmony_ci#define MIN_TXABSDELAY 0
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* Receive Interrupt Delay in units of 1.024 microseconds
568c2ecf20Sopenharmony_ci * hardware will likely hang if you set this to anything but zero.
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * Burst variant is used as default if device has FLAG2_DMA_BURST.
598c2ecf20Sopenharmony_ci *
608c2ecf20Sopenharmony_ci * Valid Range: 0-65535
618c2ecf20Sopenharmony_ci */
628c2ecf20Sopenharmony_ciE1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
638c2ecf20Sopenharmony_ci#define DEFAULT_RDTR	0
648c2ecf20Sopenharmony_ci#define BURST_RDTR	0x20
658c2ecf20Sopenharmony_ci#define MAX_RXDELAY 0xFFFF
668c2ecf20Sopenharmony_ci#define MIN_RXDELAY 0
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * Burst variant is used as default if device has FLAG2_DMA_BURST.
718c2ecf20Sopenharmony_ci *
728c2ecf20Sopenharmony_ci * Valid Range: 0-65535
738c2ecf20Sopenharmony_ci */
748c2ecf20Sopenharmony_ciE1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
758c2ecf20Sopenharmony_ci#define DEFAULT_RADV	8
768c2ecf20Sopenharmony_ci#define BURST_RADV	0x20
778c2ecf20Sopenharmony_ci#define MAX_RXABSDELAY 0xFFFF
788c2ecf20Sopenharmony_ci#define MIN_RXABSDELAY 0
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/* Interrupt Throttle Rate (interrupts/sec)
818c2ecf20Sopenharmony_ci *
828c2ecf20Sopenharmony_ci * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative
838c2ecf20Sopenharmony_ci */
848c2ecf20Sopenharmony_ciE1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
858c2ecf20Sopenharmony_ci#define DEFAULT_ITR 3
868c2ecf20Sopenharmony_ci#define MAX_ITR 100000
878c2ecf20Sopenharmony_ci#define MIN_ITR 100
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci/* IntMode (Interrupt Mode)
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci * Valid Range: varies depending on kernel configuration & hardware support
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * legacy=0, MSI=1, MSI-X=2
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * When MSI/MSI-X support is enabled in kernel-
968c2ecf20Sopenharmony_ci *   Default Value: 2 (MSI-X) when supported by hardware, 1 (MSI) otherwise
978c2ecf20Sopenharmony_ci * When MSI/MSI-X support is not enabled in kernel-
988c2ecf20Sopenharmony_ci *   Default Value: 0 (legacy)
998c2ecf20Sopenharmony_ci *
1008c2ecf20Sopenharmony_ci * When a mode is specified that is not allowed/supported, it will be
1018c2ecf20Sopenharmony_ci * demoted to the most advanced interrupt mode available.
1028c2ecf20Sopenharmony_ci */
1038c2ecf20Sopenharmony_ciE1000_PARAM(IntMode, "Interrupt Mode");
1048c2ecf20Sopenharmony_ci#define MAX_INTMODE	2
1058c2ecf20Sopenharmony_ci#define MIN_INTMODE	0
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/* Enable Smart Power Down of the PHY
1088c2ecf20Sopenharmony_ci *
1098c2ecf20Sopenharmony_ci * Valid Range: 0, 1
1108c2ecf20Sopenharmony_ci *
1118c2ecf20Sopenharmony_ci * Default Value: 0 (disabled)
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_ciE1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/* Enable Kumeran Lock Loss workaround
1168c2ecf20Sopenharmony_ci *
1178c2ecf20Sopenharmony_ci * Valid Range: 0, 1
1188c2ecf20Sopenharmony_ci *
1198c2ecf20Sopenharmony_ci * Default Value: 1 (enabled)
1208c2ecf20Sopenharmony_ci */
1218c2ecf20Sopenharmony_ciE1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/* Write Protect NVM
1248c2ecf20Sopenharmony_ci *
1258c2ecf20Sopenharmony_ci * Valid Range: 0, 1
1268c2ecf20Sopenharmony_ci *
1278c2ecf20Sopenharmony_ci * Default Value: 1 (enabled)
1288c2ecf20Sopenharmony_ci */
1298c2ecf20Sopenharmony_ciE1000_PARAM(WriteProtectNVM,
1308c2ecf20Sopenharmony_ci	    "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci/* Enable CRC Stripping
1338c2ecf20Sopenharmony_ci *
1348c2ecf20Sopenharmony_ci * Valid Range: 0, 1
1358c2ecf20Sopenharmony_ci *
1368c2ecf20Sopenharmony_ci * Default Value: 1 (enabled)
1378c2ecf20Sopenharmony_ci */
1388c2ecf20Sopenharmony_ciE1000_PARAM(CrcStripping,
1398c2ecf20Sopenharmony_ci	    "Enable CRC Stripping, disable if your BMC needs the CRC");
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistruct e1000_option {
1428c2ecf20Sopenharmony_ci	enum { enable_option, range_option, list_option } type;
1438c2ecf20Sopenharmony_ci	const char *name;
1448c2ecf20Sopenharmony_ci	const char *err;
1458c2ecf20Sopenharmony_ci	int def;
1468c2ecf20Sopenharmony_ci	union {
1478c2ecf20Sopenharmony_ci		/* range_option info */
1488c2ecf20Sopenharmony_ci		struct {
1498c2ecf20Sopenharmony_ci			int min;
1508c2ecf20Sopenharmony_ci			int max;
1518c2ecf20Sopenharmony_ci		} r;
1528c2ecf20Sopenharmony_ci		/* list_option info */
1538c2ecf20Sopenharmony_ci		struct {
1548c2ecf20Sopenharmony_ci			int nr;
1558c2ecf20Sopenharmony_ci			struct e1000_opt_list {
1568c2ecf20Sopenharmony_ci				int i;
1578c2ecf20Sopenharmony_ci				char *str;
1588c2ecf20Sopenharmony_ci			} *p;
1598c2ecf20Sopenharmony_ci		} l;
1608c2ecf20Sopenharmony_ci	} arg;
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic int e1000_validate_option(unsigned int *value,
1648c2ecf20Sopenharmony_ci				 const struct e1000_option *opt,
1658c2ecf20Sopenharmony_ci				 struct e1000_adapter *adapter)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	if (*value == OPTION_UNSET) {
1688c2ecf20Sopenharmony_ci		*value = opt->def;
1698c2ecf20Sopenharmony_ci		return 0;
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	switch (opt->type) {
1738c2ecf20Sopenharmony_ci	case enable_option:
1748c2ecf20Sopenharmony_ci		switch (*value) {
1758c2ecf20Sopenharmony_ci		case OPTION_ENABLED:
1768c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev, "%s Enabled\n",
1778c2ecf20Sopenharmony_ci				 opt->name);
1788c2ecf20Sopenharmony_ci			return 0;
1798c2ecf20Sopenharmony_ci		case OPTION_DISABLED:
1808c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev, "%s Disabled\n",
1818c2ecf20Sopenharmony_ci				 opt->name);
1828c2ecf20Sopenharmony_ci			return 0;
1838c2ecf20Sopenharmony_ci		}
1848c2ecf20Sopenharmony_ci		break;
1858c2ecf20Sopenharmony_ci	case range_option:
1868c2ecf20Sopenharmony_ci		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
1878c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev, "%s set to %i\n",
1888c2ecf20Sopenharmony_ci				 opt->name, *value);
1898c2ecf20Sopenharmony_ci			return 0;
1908c2ecf20Sopenharmony_ci		}
1918c2ecf20Sopenharmony_ci		break;
1928c2ecf20Sopenharmony_ci	case list_option: {
1938c2ecf20Sopenharmony_ci		int i;
1948c2ecf20Sopenharmony_ci		struct e1000_opt_list *ent;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci		for (i = 0; i < opt->arg.l.nr; i++) {
1978c2ecf20Sopenharmony_ci			ent = &opt->arg.l.p[i];
1988c2ecf20Sopenharmony_ci			if (*value == ent->i) {
1998c2ecf20Sopenharmony_ci				if (ent->str[0] != '\0')
2008c2ecf20Sopenharmony_ci					dev_info(&adapter->pdev->dev, "%s\n",
2018c2ecf20Sopenharmony_ci						 ent->str);
2028c2ecf20Sopenharmony_ci				return 0;
2038c2ecf20Sopenharmony_ci			}
2048c2ecf20Sopenharmony_ci		}
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci		break;
2078c2ecf20Sopenharmony_ci	default:
2088c2ecf20Sopenharmony_ci		BUG();
2098c2ecf20Sopenharmony_ci	}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	dev_info(&adapter->pdev->dev, "Invalid %s value specified (%i) %s\n",
2128c2ecf20Sopenharmony_ci		 opt->name, *value, opt->err);
2138c2ecf20Sopenharmony_ci	*value = opt->def;
2148c2ecf20Sopenharmony_ci	return -1;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci/**
2188c2ecf20Sopenharmony_ci * e1000e_check_options - Range Checking for Command Line Parameters
2198c2ecf20Sopenharmony_ci * @adapter: board private structure
2208c2ecf20Sopenharmony_ci *
2218c2ecf20Sopenharmony_ci * This routine checks all command line parameters for valid user
2228c2ecf20Sopenharmony_ci * input.  If an invalid value is given, or if no user specified
2238c2ecf20Sopenharmony_ci * value exists, a default value is used.  The final value is stored
2248c2ecf20Sopenharmony_ci * in a variable in the adapter structure.
2258c2ecf20Sopenharmony_ci **/
2268c2ecf20Sopenharmony_civoid e1000e_check_options(struct e1000_adapter *adapter)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
2298c2ecf20Sopenharmony_ci	int bd = adapter->bd_number;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (bd >= E1000_MAX_NIC) {
2328c2ecf20Sopenharmony_ci		dev_notice(&adapter->pdev->dev,
2338c2ecf20Sopenharmony_ci			   "Warning: no configuration for board #%i\n", bd);
2348c2ecf20Sopenharmony_ci		dev_notice(&adapter->pdev->dev,
2358c2ecf20Sopenharmony_ci			   "Using defaults for all values\n");
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	/* Transmit Interrupt Delay */
2398c2ecf20Sopenharmony_ci	{
2408c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
2418c2ecf20Sopenharmony_ci			.type = range_option,
2428c2ecf20Sopenharmony_ci			.name = "Transmit Interrupt Delay",
2438c2ecf20Sopenharmony_ci			.err  = "using default of "
2448c2ecf20Sopenharmony_ci				__MODULE_STRING(DEFAULT_TIDV),
2458c2ecf20Sopenharmony_ci			.def  = DEFAULT_TIDV,
2468c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_TXDELAY,
2478c2ecf20Sopenharmony_ci					 .max = MAX_TXDELAY } }
2488c2ecf20Sopenharmony_ci		};
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci		if (num_TxIntDelay > bd) {
2518c2ecf20Sopenharmony_ci			adapter->tx_int_delay = TxIntDelay[bd];
2528c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->tx_int_delay, &opt,
2538c2ecf20Sopenharmony_ci					      adapter);
2548c2ecf20Sopenharmony_ci		} else {
2558c2ecf20Sopenharmony_ci			adapter->tx_int_delay = opt.def;
2568c2ecf20Sopenharmony_ci		}
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci	/* Transmit Absolute Interrupt Delay */
2598c2ecf20Sopenharmony_ci	{
2608c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
2618c2ecf20Sopenharmony_ci			.type = range_option,
2628c2ecf20Sopenharmony_ci			.name = "Transmit Absolute Interrupt Delay",
2638c2ecf20Sopenharmony_ci			.err  = "using default of "
2648c2ecf20Sopenharmony_ci				__MODULE_STRING(DEFAULT_TADV),
2658c2ecf20Sopenharmony_ci			.def  = DEFAULT_TADV,
2668c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_TXABSDELAY,
2678c2ecf20Sopenharmony_ci					 .max = MAX_TXABSDELAY } }
2688c2ecf20Sopenharmony_ci		};
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci		if (num_TxAbsIntDelay > bd) {
2718c2ecf20Sopenharmony_ci			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
2728c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
2738c2ecf20Sopenharmony_ci					      adapter);
2748c2ecf20Sopenharmony_ci		} else {
2758c2ecf20Sopenharmony_ci			adapter->tx_abs_int_delay = opt.def;
2768c2ecf20Sopenharmony_ci		}
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci	/* Receive Interrupt Delay */
2798c2ecf20Sopenharmony_ci	{
2808c2ecf20Sopenharmony_ci		static struct e1000_option opt = {
2818c2ecf20Sopenharmony_ci			.type = range_option,
2828c2ecf20Sopenharmony_ci			.name = "Receive Interrupt Delay",
2838c2ecf20Sopenharmony_ci			.err  = "using default of "
2848c2ecf20Sopenharmony_ci				__MODULE_STRING(DEFAULT_RDTR),
2858c2ecf20Sopenharmony_ci			.def  = DEFAULT_RDTR,
2868c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_RXDELAY,
2878c2ecf20Sopenharmony_ci					 .max = MAX_RXDELAY } }
2888c2ecf20Sopenharmony_ci		};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci		if (adapter->flags2 & FLAG2_DMA_BURST)
2918c2ecf20Sopenharmony_ci			opt.def = BURST_RDTR;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci		if (num_RxIntDelay > bd) {
2948c2ecf20Sopenharmony_ci			adapter->rx_int_delay = RxIntDelay[bd];
2958c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->rx_int_delay, &opt,
2968c2ecf20Sopenharmony_ci					      adapter);
2978c2ecf20Sopenharmony_ci		} else {
2988c2ecf20Sopenharmony_ci			adapter->rx_int_delay = opt.def;
2998c2ecf20Sopenharmony_ci		}
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci	/* Receive Absolute Interrupt Delay */
3028c2ecf20Sopenharmony_ci	{
3038c2ecf20Sopenharmony_ci		static struct e1000_option opt = {
3048c2ecf20Sopenharmony_ci			.type = range_option,
3058c2ecf20Sopenharmony_ci			.name = "Receive Absolute Interrupt Delay",
3068c2ecf20Sopenharmony_ci			.err  = "using default of "
3078c2ecf20Sopenharmony_ci				__MODULE_STRING(DEFAULT_RADV),
3088c2ecf20Sopenharmony_ci			.def  = DEFAULT_RADV,
3098c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_RXABSDELAY,
3108c2ecf20Sopenharmony_ci					 .max = MAX_RXABSDELAY } }
3118c2ecf20Sopenharmony_ci		};
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		if (adapter->flags2 & FLAG2_DMA_BURST)
3148c2ecf20Sopenharmony_ci			opt.def = BURST_RADV;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci		if (num_RxAbsIntDelay > bd) {
3178c2ecf20Sopenharmony_ci			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
3188c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
3198c2ecf20Sopenharmony_ci					      adapter);
3208c2ecf20Sopenharmony_ci		} else {
3218c2ecf20Sopenharmony_ci			adapter->rx_abs_int_delay = opt.def;
3228c2ecf20Sopenharmony_ci		}
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci	/* Interrupt Throttling Rate */
3258c2ecf20Sopenharmony_ci	{
3268c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
3278c2ecf20Sopenharmony_ci			.type = range_option,
3288c2ecf20Sopenharmony_ci			.name = "Interrupt Throttling Rate (ints/sec)",
3298c2ecf20Sopenharmony_ci			.err  = "using default of "
3308c2ecf20Sopenharmony_ci				__MODULE_STRING(DEFAULT_ITR),
3318c2ecf20Sopenharmony_ci			.def  = DEFAULT_ITR,
3328c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_ITR,
3338c2ecf20Sopenharmony_ci					 .max = MAX_ITR } }
3348c2ecf20Sopenharmony_ci		};
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci		if (num_InterruptThrottleRate > bd) {
3378c2ecf20Sopenharmony_ci			adapter->itr = InterruptThrottleRate[bd];
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci			/* Make sure a message is printed for non-special
3408c2ecf20Sopenharmony_ci			 * values. And in case of an invalid option, display
3418c2ecf20Sopenharmony_ci			 * warning, use default and go through itr/itr_setting
3428c2ecf20Sopenharmony_ci			 * adjustment logic below
3438c2ecf20Sopenharmony_ci			 */
3448c2ecf20Sopenharmony_ci			if ((adapter->itr > 4) &&
3458c2ecf20Sopenharmony_ci			    e1000_validate_option(&adapter->itr, &opt, adapter))
3468c2ecf20Sopenharmony_ci				adapter->itr = opt.def;
3478c2ecf20Sopenharmony_ci		} else {
3488c2ecf20Sopenharmony_ci			/* If no option specified, use default value and go
3498c2ecf20Sopenharmony_ci			 * through the logic below to adjust itr/itr_setting
3508c2ecf20Sopenharmony_ci			 */
3518c2ecf20Sopenharmony_ci			adapter->itr = opt.def;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci			/* Make sure a message is printed for non-special
3548c2ecf20Sopenharmony_ci			 * default values
3558c2ecf20Sopenharmony_ci			 */
3568c2ecf20Sopenharmony_ci			if (adapter->itr > 4)
3578c2ecf20Sopenharmony_ci				dev_info(&adapter->pdev->dev,
3588c2ecf20Sopenharmony_ci					 "%s set to default %d\n", opt.name,
3598c2ecf20Sopenharmony_ci					 adapter->itr);
3608c2ecf20Sopenharmony_ci		}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci		adapter->itr_setting = adapter->itr;
3638c2ecf20Sopenharmony_ci		switch (adapter->itr) {
3648c2ecf20Sopenharmony_ci		case 0:
3658c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev, "%s turned off\n",
3668c2ecf20Sopenharmony_ci				 opt.name);
3678c2ecf20Sopenharmony_ci			break;
3688c2ecf20Sopenharmony_ci		case 1:
3698c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev,
3708c2ecf20Sopenharmony_ci				 "%s set to dynamic mode\n", opt.name);
3718c2ecf20Sopenharmony_ci			adapter->itr = 20000;
3728c2ecf20Sopenharmony_ci			break;
3738c2ecf20Sopenharmony_ci		case 2:
3748c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev,
3758c2ecf20Sopenharmony_ci				 "%s Invalid mode - setting default\n",
3768c2ecf20Sopenharmony_ci				 opt.name);
3778c2ecf20Sopenharmony_ci			adapter->itr_setting = opt.def;
3788c2ecf20Sopenharmony_ci			fallthrough;
3798c2ecf20Sopenharmony_ci		case 3:
3808c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev,
3818c2ecf20Sopenharmony_ci				 "%s set to dynamic conservative mode\n",
3828c2ecf20Sopenharmony_ci				 opt.name);
3838c2ecf20Sopenharmony_ci			adapter->itr = 20000;
3848c2ecf20Sopenharmony_ci			break;
3858c2ecf20Sopenharmony_ci		case 4:
3868c2ecf20Sopenharmony_ci			dev_info(&adapter->pdev->dev,
3878c2ecf20Sopenharmony_ci				 "%s set to simplified (2000-8000 ints) mode\n",
3888c2ecf20Sopenharmony_ci				 opt.name);
3898c2ecf20Sopenharmony_ci			break;
3908c2ecf20Sopenharmony_ci		default:
3918c2ecf20Sopenharmony_ci			/* Save the setting, because the dynamic bits
3928c2ecf20Sopenharmony_ci			 * change itr.
3938c2ecf20Sopenharmony_ci			 *
3948c2ecf20Sopenharmony_ci			 * Clear the lower two bits because
3958c2ecf20Sopenharmony_ci			 * they are used as control.
3968c2ecf20Sopenharmony_ci			 */
3978c2ecf20Sopenharmony_ci			adapter->itr_setting &= ~3;
3988c2ecf20Sopenharmony_ci			break;
3998c2ecf20Sopenharmony_ci		}
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci	/* Interrupt Mode */
4028c2ecf20Sopenharmony_ci	{
4038c2ecf20Sopenharmony_ci		static struct e1000_option opt = {
4048c2ecf20Sopenharmony_ci			.type = range_option,
4058c2ecf20Sopenharmony_ci			.name = "Interrupt Mode",
4068c2ecf20Sopenharmony_ci#ifndef CONFIG_PCI_MSI
4078c2ecf20Sopenharmony_ci			.err  = "defaulting to 0 (legacy)",
4088c2ecf20Sopenharmony_ci			.def  = E1000E_INT_MODE_LEGACY,
4098c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = 0,
4108c2ecf20Sopenharmony_ci					 .max = 0 } }
4118c2ecf20Sopenharmony_ci#endif
4128c2ecf20Sopenharmony_ci		};
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_MSI
4158c2ecf20Sopenharmony_ci		if (adapter->flags & FLAG_HAS_MSIX) {
4168c2ecf20Sopenharmony_ci			opt.err = kstrdup("defaulting to 2 (MSI-X)",
4178c2ecf20Sopenharmony_ci					  GFP_KERNEL);
4188c2ecf20Sopenharmony_ci			opt.def = E1000E_INT_MODE_MSIX;
4198c2ecf20Sopenharmony_ci			opt.arg.r.max = E1000E_INT_MODE_MSIX;
4208c2ecf20Sopenharmony_ci		} else {
4218c2ecf20Sopenharmony_ci			opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL);
4228c2ecf20Sopenharmony_ci			opt.def = E1000E_INT_MODE_MSI;
4238c2ecf20Sopenharmony_ci			opt.arg.r.max = E1000E_INT_MODE_MSI;
4248c2ecf20Sopenharmony_ci		}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci		if (!opt.err) {
4278c2ecf20Sopenharmony_ci			dev_err(&adapter->pdev->dev,
4288c2ecf20Sopenharmony_ci				"Failed to allocate memory\n");
4298c2ecf20Sopenharmony_ci			return;
4308c2ecf20Sopenharmony_ci		}
4318c2ecf20Sopenharmony_ci#endif
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci		if (num_IntMode > bd) {
4348c2ecf20Sopenharmony_ci			unsigned int int_mode = IntMode[bd];
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci			e1000_validate_option(&int_mode, &opt, adapter);
4378c2ecf20Sopenharmony_ci			adapter->int_mode = int_mode;
4388c2ecf20Sopenharmony_ci		} else {
4398c2ecf20Sopenharmony_ci			adapter->int_mode = opt.def;
4408c2ecf20Sopenharmony_ci		}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_MSI
4438c2ecf20Sopenharmony_ci		kfree(opt.err);
4448c2ecf20Sopenharmony_ci#endif
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci	/* Smart Power Down */
4478c2ecf20Sopenharmony_ci	{
4488c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
4498c2ecf20Sopenharmony_ci			.type = enable_option,
4508c2ecf20Sopenharmony_ci			.name = "PHY Smart Power Down",
4518c2ecf20Sopenharmony_ci			.err  = "defaulting to Disabled",
4528c2ecf20Sopenharmony_ci			.def  = OPTION_DISABLED
4538c2ecf20Sopenharmony_ci		};
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci		if (num_SmartPowerDownEnable > bd) {
4568c2ecf20Sopenharmony_ci			unsigned int spd = SmartPowerDownEnable[bd];
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci			e1000_validate_option(&spd, &opt, adapter);
4598c2ecf20Sopenharmony_ci			if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && spd)
4608c2ecf20Sopenharmony_ci				adapter->flags |= FLAG_SMART_POWER_DOWN;
4618c2ecf20Sopenharmony_ci		}
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci	/* CRC Stripping */
4648c2ecf20Sopenharmony_ci	{
4658c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
4668c2ecf20Sopenharmony_ci			.type = enable_option,
4678c2ecf20Sopenharmony_ci			.name = "CRC Stripping",
4688c2ecf20Sopenharmony_ci			.err  = "defaulting to Enabled",
4698c2ecf20Sopenharmony_ci			.def  = OPTION_ENABLED
4708c2ecf20Sopenharmony_ci		};
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		if (num_CrcStripping > bd) {
4738c2ecf20Sopenharmony_ci			unsigned int crc_stripping = CrcStripping[bd];
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci			e1000_validate_option(&crc_stripping, &opt, adapter);
4768c2ecf20Sopenharmony_ci			if (crc_stripping == OPTION_ENABLED) {
4778c2ecf20Sopenharmony_ci				adapter->flags2 |= FLAG2_CRC_STRIPPING;
4788c2ecf20Sopenharmony_ci				adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
4798c2ecf20Sopenharmony_ci			}
4808c2ecf20Sopenharmony_ci		} else {
4818c2ecf20Sopenharmony_ci			adapter->flags2 |= FLAG2_CRC_STRIPPING;
4828c2ecf20Sopenharmony_ci			adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
4838c2ecf20Sopenharmony_ci		}
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci	/* Kumeran Lock Loss Workaround */
4868c2ecf20Sopenharmony_ci	{
4878c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
4888c2ecf20Sopenharmony_ci			.type = enable_option,
4898c2ecf20Sopenharmony_ci			.name = "Kumeran Lock Loss Workaround",
4908c2ecf20Sopenharmony_ci			.err  = "defaulting to Enabled",
4918c2ecf20Sopenharmony_ci			.def  = OPTION_ENABLED
4928c2ecf20Sopenharmony_ci		};
4938c2ecf20Sopenharmony_ci		bool enabled = opt.def;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci		if (num_KumeranLockLoss > bd) {
4968c2ecf20Sopenharmony_ci			unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci			e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
4998c2ecf20Sopenharmony_ci			enabled = kmrn_lock_loss;
5008c2ecf20Sopenharmony_ci		}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci		if (hw->mac.type == e1000_ich8lan)
5038c2ecf20Sopenharmony_ci			e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
5048c2ecf20Sopenharmony_ci								     enabled);
5058c2ecf20Sopenharmony_ci	}
5068c2ecf20Sopenharmony_ci	/* Write-protect NVM */
5078c2ecf20Sopenharmony_ci	{
5088c2ecf20Sopenharmony_ci		static const struct e1000_option opt = {
5098c2ecf20Sopenharmony_ci			.type = enable_option,
5108c2ecf20Sopenharmony_ci			.name = "Write-protect NVM",
5118c2ecf20Sopenharmony_ci			.err  = "defaulting to Enabled",
5128c2ecf20Sopenharmony_ci			.def  = OPTION_ENABLED
5138c2ecf20Sopenharmony_ci		};
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci		if (adapter->flags & FLAG_IS_ICH) {
5168c2ecf20Sopenharmony_ci			if (num_WriteProtectNVM > bd) {
5178c2ecf20Sopenharmony_ci				unsigned int write_protect_nvm =
5188c2ecf20Sopenharmony_ci				    WriteProtectNVM[bd];
5198c2ecf20Sopenharmony_ci				e1000_validate_option(&write_protect_nvm, &opt,
5208c2ecf20Sopenharmony_ci						      adapter);
5218c2ecf20Sopenharmony_ci				if (write_protect_nvm)
5228c2ecf20Sopenharmony_ci					adapter->flags |= FLAG_READ_ONLY_NVM;
5238c2ecf20Sopenharmony_ci			} else {
5248c2ecf20Sopenharmony_ci				if (opt.def)
5258c2ecf20Sopenharmony_ci					adapter->flags |= FLAG_READ_ONLY_NVM;
5268c2ecf20Sopenharmony_ci			}
5278c2ecf20Sopenharmony_ci		}
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci}
530