18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2006 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include "e1000.h"
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci/* This is the only thing that needs to be changed to adjust the
78c2ecf20Sopenharmony_ci * maximum number of ports that the driver can manage.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define E1000_MAX_NIC 32
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#define OPTION_UNSET   -1
138c2ecf20Sopenharmony_ci#define OPTION_DISABLED 0
148c2ecf20Sopenharmony_ci#define OPTION_ENABLED  1
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* All parameters are treated the same, as an integer array of values.
178c2ecf20Sopenharmony_ci * This macro just reduces the need to repeat the same declaration code
188c2ecf20Sopenharmony_ci * over and over (plus this helps to avoid typo bugs).
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
228c2ecf20Sopenharmony_ci#define E1000_PARAM(X, desc) \
238c2ecf20Sopenharmony_ci	static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
248c2ecf20Sopenharmony_ci	static unsigned int num_##X; \
258c2ecf20Sopenharmony_ci	module_param_array_named(X, X, int, &num_##X, 0); \
268c2ecf20Sopenharmony_ci	MODULE_PARM_DESC(X, desc);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* Transmit Descriptor Count
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
318c2ecf20Sopenharmony_ci * Valid Range: 80-4096 for 82544 and newer
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * Default Value: 256
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ciE1000_PARAM(TxDescriptors, "Number of transmit descriptors");
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* Receive Descriptor Count
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
408c2ecf20Sopenharmony_ci * Valid Range: 80-4096 for 82544 and newer
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * Default Value: 256
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_ciE1000_PARAM(RxDescriptors, "Number of receive descriptors");
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* User Specified Speed Override
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * Valid Range: 0, 10, 100, 1000
498c2ecf20Sopenharmony_ci *  - 0    - auto-negotiate at all supported speeds
508c2ecf20Sopenharmony_ci *  - 10   - only link at 10 Mbps
518c2ecf20Sopenharmony_ci *  - 100  - only link at 100 Mbps
528c2ecf20Sopenharmony_ci *  - 1000 - only link at 1000 Mbps
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * Default Value: 0
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_ciE1000_PARAM(Speed, "Speed setting");
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* User Specified Duplex Override
598c2ecf20Sopenharmony_ci *
608c2ecf20Sopenharmony_ci * Valid Range: 0-2
618c2ecf20Sopenharmony_ci *  - 0 - auto-negotiate for duplex
628c2ecf20Sopenharmony_ci *  - 1 - only link at half duplex
638c2ecf20Sopenharmony_ci *  - 2 - only link at full duplex
648c2ecf20Sopenharmony_ci *
658c2ecf20Sopenharmony_ci * Default Value: 0
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_ciE1000_PARAM(Duplex, "Duplex setting");
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* Auto-negotiation Advertisement Override
708c2ecf20Sopenharmony_ci *
718c2ecf20Sopenharmony_ci * Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * The AutoNeg value is a bit mask describing which speed and duplex
748c2ecf20Sopenharmony_ci * combinations should be advertised during auto-negotiation.
758c2ecf20Sopenharmony_ci * The supported speed and duplex modes are listed below
768c2ecf20Sopenharmony_ci *
778c2ecf20Sopenharmony_ci * Bit           7     6     5      4      3     2     1      0
788c2ecf20Sopenharmony_ci * Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
798c2ecf20Sopenharmony_ci * Duplex                    Full          Full  Half  Full   Half
808c2ecf20Sopenharmony_ci *
818c2ecf20Sopenharmony_ci * Default Value: 0x2F (copper); 0x20 (fiber)
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_ciE1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
848c2ecf20Sopenharmony_ci#define AUTONEG_ADV_DEFAULT  0x2F
858c2ecf20Sopenharmony_ci#define AUTONEG_ADV_MASK     0x2F
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* User Specified Flow Control Override
888c2ecf20Sopenharmony_ci *
898c2ecf20Sopenharmony_ci * Valid Range: 0-3
908c2ecf20Sopenharmony_ci *  - 0 - No Flow Control
918c2ecf20Sopenharmony_ci *  - 1 - Rx only, respond to PAUSE frames but do not generate them
928c2ecf20Sopenharmony_ci *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
938c2ecf20Sopenharmony_ci *  - 3 - Full Flow Control Support
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * Default Value: Read flow control settings from the EEPROM
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_ciE1000_PARAM(FlowControl, "Flow Control setting");
988c2ecf20Sopenharmony_ci#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* XsumRX - Receive Checksum Offload Enable/Disable
1018c2ecf20Sopenharmony_ci *
1028c2ecf20Sopenharmony_ci * Valid Range: 0, 1
1038c2ecf20Sopenharmony_ci *  - 0 - disables all checksum offload
1048c2ecf20Sopenharmony_ci *  - 1 - enables receive IP/TCP/UDP checksum offload
1058c2ecf20Sopenharmony_ci *        on 82543 and newer -based NICs
1068c2ecf20Sopenharmony_ci *
1078c2ecf20Sopenharmony_ci * Default Value: 1
1088c2ecf20Sopenharmony_ci */
1098c2ecf20Sopenharmony_ciE1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci/* Transmit Interrupt Delay in units of 1.024 microseconds
1128c2ecf20Sopenharmony_ci *  Tx interrupt delay needs to typically be set to something non zero
1138c2ecf20Sopenharmony_ci *
1148c2ecf20Sopenharmony_ci * Valid Range: 0-65535
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_ciE1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
1178c2ecf20Sopenharmony_ci#define DEFAULT_TIDV                   8
1188c2ecf20Sopenharmony_ci#define MAX_TXDELAY               0xFFFF
1198c2ecf20Sopenharmony_ci#define MIN_TXDELAY                    0
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
1228c2ecf20Sopenharmony_ci *
1238c2ecf20Sopenharmony_ci * Valid Range: 0-65535
1248c2ecf20Sopenharmony_ci */
1258c2ecf20Sopenharmony_ciE1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
1268c2ecf20Sopenharmony_ci#define DEFAULT_TADV                  32
1278c2ecf20Sopenharmony_ci#define MAX_TXABSDELAY            0xFFFF
1288c2ecf20Sopenharmony_ci#define MIN_TXABSDELAY                 0
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/* Receive Interrupt Delay in units of 1.024 microseconds
1318c2ecf20Sopenharmony_ci *   hardware will likely hang if you set this to anything but zero.
1328c2ecf20Sopenharmony_ci *
1338c2ecf20Sopenharmony_ci * Valid Range: 0-65535
1348c2ecf20Sopenharmony_ci */
1358c2ecf20Sopenharmony_ciE1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
1368c2ecf20Sopenharmony_ci#define DEFAULT_RDTR                   0
1378c2ecf20Sopenharmony_ci#define MAX_RXDELAY               0xFFFF
1388c2ecf20Sopenharmony_ci#define MIN_RXDELAY                    0
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
1418c2ecf20Sopenharmony_ci *
1428c2ecf20Sopenharmony_ci * Valid Range: 0-65535
1438c2ecf20Sopenharmony_ci */
1448c2ecf20Sopenharmony_ciE1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
1458c2ecf20Sopenharmony_ci#define DEFAULT_RADV                   8
1468c2ecf20Sopenharmony_ci#define MAX_RXABSDELAY            0xFFFF
1478c2ecf20Sopenharmony_ci#define MIN_RXABSDELAY                 0
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/* Interrupt Throttle Rate (interrupts/sec)
1508c2ecf20Sopenharmony_ci *
1518c2ecf20Sopenharmony_ci * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_ciE1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
1548c2ecf20Sopenharmony_ci#define DEFAULT_ITR                    3
1558c2ecf20Sopenharmony_ci#define MAX_ITR                   100000
1568c2ecf20Sopenharmony_ci#define MIN_ITR                      100
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci/* Enable Smart Power Down of the PHY
1598c2ecf20Sopenharmony_ci *
1608c2ecf20Sopenharmony_ci * Valid Range: 0, 1
1618c2ecf20Sopenharmony_ci *
1628c2ecf20Sopenharmony_ci * Default Value: 0 (disabled)
1638c2ecf20Sopenharmony_ci */
1648c2ecf20Sopenharmony_ciE1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistruct e1000_option {
1678c2ecf20Sopenharmony_ci	enum { enable_option, range_option, list_option } type;
1688c2ecf20Sopenharmony_ci	const char *name;
1698c2ecf20Sopenharmony_ci	const char *err;
1708c2ecf20Sopenharmony_ci	int def;
1718c2ecf20Sopenharmony_ci	union {
1728c2ecf20Sopenharmony_ci		struct { /* range_option info */
1738c2ecf20Sopenharmony_ci			int min;
1748c2ecf20Sopenharmony_ci			int max;
1758c2ecf20Sopenharmony_ci		} r;
1768c2ecf20Sopenharmony_ci		struct { /* list_option info */
1778c2ecf20Sopenharmony_ci			int nr;
1788c2ecf20Sopenharmony_ci			const struct e1000_opt_list { int i; char *str; } *p;
1798c2ecf20Sopenharmony_ci		} l;
1808c2ecf20Sopenharmony_ci	} arg;
1818c2ecf20Sopenharmony_ci};
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic int e1000_validate_option(unsigned int *value,
1848c2ecf20Sopenharmony_ci				 const struct e1000_option *opt,
1858c2ecf20Sopenharmony_ci				 struct e1000_adapter *adapter)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	if (*value == OPTION_UNSET) {
1888c2ecf20Sopenharmony_ci		*value = opt->def;
1898c2ecf20Sopenharmony_ci		return 0;
1908c2ecf20Sopenharmony_ci	}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	switch (opt->type) {
1938c2ecf20Sopenharmony_ci	case enable_option:
1948c2ecf20Sopenharmony_ci		switch (*value) {
1958c2ecf20Sopenharmony_ci		case OPTION_ENABLED:
1968c2ecf20Sopenharmony_ci			e_dev_info("%s Enabled\n", opt->name);
1978c2ecf20Sopenharmony_ci			return 0;
1988c2ecf20Sopenharmony_ci		case OPTION_DISABLED:
1998c2ecf20Sopenharmony_ci			e_dev_info("%s Disabled\n", opt->name);
2008c2ecf20Sopenharmony_ci			return 0;
2018c2ecf20Sopenharmony_ci		}
2028c2ecf20Sopenharmony_ci		break;
2038c2ecf20Sopenharmony_ci	case range_option:
2048c2ecf20Sopenharmony_ci		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
2058c2ecf20Sopenharmony_ci			e_dev_info("%s set to %i\n", opt->name, *value);
2068c2ecf20Sopenharmony_ci			return 0;
2078c2ecf20Sopenharmony_ci		}
2088c2ecf20Sopenharmony_ci		break;
2098c2ecf20Sopenharmony_ci	case list_option: {
2108c2ecf20Sopenharmony_ci		int i;
2118c2ecf20Sopenharmony_ci		const struct e1000_opt_list *ent;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		for (i = 0; i < opt->arg.l.nr; i++) {
2148c2ecf20Sopenharmony_ci			ent = &opt->arg.l.p[i];
2158c2ecf20Sopenharmony_ci			if (*value == ent->i) {
2168c2ecf20Sopenharmony_ci				if (ent->str[0] != '\0')
2178c2ecf20Sopenharmony_ci					e_dev_info("%s\n", ent->str);
2188c2ecf20Sopenharmony_ci				return 0;
2198c2ecf20Sopenharmony_ci			}
2208c2ecf20Sopenharmony_ci		}
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci		break;
2238c2ecf20Sopenharmony_ci	default:
2248c2ecf20Sopenharmony_ci		BUG();
2258c2ecf20Sopenharmony_ci	}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	e_dev_info("Invalid %s value specified (%i) %s\n",
2288c2ecf20Sopenharmony_ci	       opt->name, *value, opt->err);
2298c2ecf20Sopenharmony_ci	*value = opt->def;
2308c2ecf20Sopenharmony_ci	return -1;
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistatic void e1000_check_fiber_options(struct e1000_adapter *adapter);
2348c2ecf20Sopenharmony_cistatic void e1000_check_copper_options(struct e1000_adapter *adapter);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci/**
2378c2ecf20Sopenharmony_ci * e1000_check_options - Range Checking for Command Line Parameters
2388c2ecf20Sopenharmony_ci * @adapter: board private structure
2398c2ecf20Sopenharmony_ci *
2408c2ecf20Sopenharmony_ci * This routine checks all command line parameters for valid user
2418c2ecf20Sopenharmony_ci * input.  If an invalid value is given, or if no user specified
2428c2ecf20Sopenharmony_ci * value exists, a default value is used.  The final value is stored
2438c2ecf20Sopenharmony_ci * in a variable in the adapter structure.
2448c2ecf20Sopenharmony_ci **/
2458c2ecf20Sopenharmony_civoid e1000_check_options(struct e1000_adapter *adapter)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct e1000_option opt;
2488c2ecf20Sopenharmony_ci	int bd = adapter->bd_number;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (bd >= E1000_MAX_NIC) {
2518c2ecf20Sopenharmony_ci		e_dev_warn("Warning: no configuration for board #%i "
2528c2ecf20Sopenharmony_ci			   "using defaults for all values\n", bd);
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	{ /* Transmit Descriptor Count */
2568c2ecf20Sopenharmony_ci		struct e1000_tx_ring *tx_ring = adapter->tx_ring;
2578c2ecf20Sopenharmony_ci		int i;
2588c2ecf20Sopenharmony_ci		e1000_mac_type mac_type = adapter->hw.mac_type;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
2618c2ecf20Sopenharmony_ci			.type = range_option,
2628c2ecf20Sopenharmony_ci			.name = "Transmit Descriptors",
2638c2ecf20Sopenharmony_ci			.err  = "using default of "
2648c2ecf20Sopenharmony_ci				__MODULE_STRING(E1000_DEFAULT_TXD),
2658c2ecf20Sopenharmony_ci			.def  = E1000_DEFAULT_TXD,
2668c2ecf20Sopenharmony_ci			.arg  = { .r = {
2678c2ecf20Sopenharmony_ci				.min = E1000_MIN_TXD,
2688c2ecf20Sopenharmony_ci				.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
2698c2ecf20Sopenharmony_ci				}}
2708c2ecf20Sopenharmony_ci		};
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		if (num_TxDescriptors > bd) {
2738c2ecf20Sopenharmony_ci			tx_ring->count = TxDescriptors[bd];
2748c2ecf20Sopenharmony_ci			e1000_validate_option(&tx_ring->count, &opt, adapter);
2758c2ecf20Sopenharmony_ci			tx_ring->count = ALIGN(tx_ring->count,
2768c2ecf20Sopenharmony_ci						REQ_TX_DESCRIPTOR_MULTIPLE);
2778c2ecf20Sopenharmony_ci		} else {
2788c2ecf20Sopenharmony_ci			tx_ring->count = opt.def;
2798c2ecf20Sopenharmony_ci		}
2808c2ecf20Sopenharmony_ci		for (i = 0; i < adapter->num_tx_queues; i++)
2818c2ecf20Sopenharmony_ci			tx_ring[i].count = tx_ring->count;
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci	{ /* Receive Descriptor Count */
2848c2ecf20Sopenharmony_ci		struct e1000_rx_ring *rx_ring = adapter->rx_ring;
2858c2ecf20Sopenharmony_ci		int i;
2868c2ecf20Sopenharmony_ci		e1000_mac_type mac_type = adapter->hw.mac_type;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
2898c2ecf20Sopenharmony_ci			.type = range_option,
2908c2ecf20Sopenharmony_ci			.name = "Receive Descriptors",
2918c2ecf20Sopenharmony_ci			.err  = "using default of "
2928c2ecf20Sopenharmony_ci				__MODULE_STRING(E1000_DEFAULT_RXD),
2938c2ecf20Sopenharmony_ci			.def  = E1000_DEFAULT_RXD,
2948c2ecf20Sopenharmony_ci			.arg  = { .r = {
2958c2ecf20Sopenharmony_ci				.min = E1000_MIN_RXD,
2968c2ecf20Sopenharmony_ci				.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
2978c2ecf20Sopenharmony_ci				       E1000_MAX_82544_RXD
2988c2ecf20Sopenharmony_ci			}}
2998c2ecf20Sopenharmony_ci		};
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		if (num_RxDescriptors > bd) {
3028c2ecf20Sopenharmony_ci			rx_ring->count = RxDescriptors[bd];
3038c2ecf20Sopenharmony_ci			e1000_validate_option(&rx_ring->count, &opt, adapter);
3048c2ecf20Sopenharmony_ci			rx_ring->count = ALIGN(rx_ring->count,
3058c2ecf20Sopenharmony_ci						REQ_RX_DESCRIPTOR_MULTIPLE);
3068c2ecf20Sopenharmony_ci		} else {
3078c2ecf20Sopenharmony_ci			rx_ring->count = opt.def;
3088c2ecf20Sopenharmony_ci		}
3098c2ecf20Sopenharmony_ci		for (i = 0; i < adapter->num_rx_queues; i++)
3108c2ecf20Sopenharmony_ci			rx_ring[i].count = rx_ring->count;
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci	{ /* Checksum Offload Enable/Disable */
3138c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
3148c2ecf20Sopenharmony_ci			.type = enable_option,
3158c2ecf20Sopenharmony_ci			.name = "Checksum Offload",
3168c2ecf20Sopenharmony_ci			.err  = "defaulting to Enabled",
3178c2ecf20Sopenharmony_ci			.def  = OPTION_ENABLED
3188c2ecf20Sopenharmony_ci		};
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		if (num_XsumRX > bd) {
3218c2ecf20Sopenharmony_ci			unsigned int rx_csum = XsumRX[bd];
3228c2ecf20Sopenharmony_ci			e1000_validate_option(&rx_csum, &opt, adapter);
3238c2ecf20Sopenharmony_ci			adapter->rx_csum = rx_csum;
3248c2ecf20Sopenharmony_ci		} else {
3258c2ecf20Sopenharmony_ci			adapter->rx_csum = opt.def;
3268c2ecf20Sopenharmony_ci		}
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci	{ /* Flow Control */
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		static const struct e1000_opt_list fc_list[] = {
3318c2ecf20Sopenharmony_ci		       { E1000_FC_NONE, "Flow Control Disabled" },
3328c2ecf20Sopenharmony_ci		       { E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
3338c2ecf20Sopenharmony_ci		       { E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
3348c2ecf20Sopenharmony_ci		       { E1000_FC_FULL, "Flow Control Enabled" },
3358c2ecf20Sopenharmony_ci		       { E1000_FC_DEFAULT, "Flow Control Hardware Default" }
3368c2ecf20Sopenharmony_ci		};
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
3398c2ecf20Sopenharmony_ci			.type = list_option,
3408c2ecf20Sopenharmony_ci			.name = "Flow Control",
3418c2ecf20Sopenharmony_ci			.err  = "reading default settings from EEPROM",
3428c2ecf20Sopenharmony_ci			.def  = E1000_FC_DEFAULT,
3438c2ecf20Sopenharmony_ci			.arg  = { .l = { .nr = ARRAY_SIZE(fc_list),
3448c2ecf20Sopenharmony_ci					 .p = fc_list }}
3458c2ecf20Sopenharmony_ci		};
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci		if (num_FlowControl > bd) {
3488c2ecf20Sopenharmony_ci			unsigned int fc = FlowControl[bd];
3498c2ecf20Sopenharmony_ci			e1000_validate_option(&fc, &opt, adapter);
3508c2ecf20Sopenharmony_ci			adapter->hw.fc = adapter->hw.original_fc = fc;
3518c2ecf20Sopenharmony_ci		} else {
3528c2ecf20Sopenharmony_ci			adapter->hw.fc = adapter->hw.original_fc = opt.def;
3538c2ecf20Sopenharmony_ci		}
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci	{ /* Transmit Interrupt Delay */
3568c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
3578c2ecf20Sopenharmony_ci			.type = range_option,
3588c2ecf20Sopenharmony_ci			.name = "Transmit Interrupt Delay",
3598c2ecf20Sopenharmony_ci			.err  = "using default of " __MODULE_STRING(DEFAULT_TIDV),
3608c2ecf20Sopenharmony_ci			.def  = DEFAULT_TIDV,
3618c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_TXDELAY,
3628c2ecf20Sopenharmony_ci					 .max = MAX_TXDELAY }}
3638c2ecf20Sopenharmony_ci		};
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		if (num_TxIntDelay > bd) {
3668c2ecf20Sopenharmony_ci			adapter->tx_int_delay = TxIntDelay[bd];
3678c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->tx_int_delay, &opt,
3688c2ecf20Sopenharmony_ci			                      adapter);
3698c2ecf20Sopenharmony_ci		} else {
3708c2ecf20Sopenharmony_ci			adapter->tx_int_delay = opt.def;
3718c2ecf20Sopenharmony_ci		}
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci	{ /* Transmit Absolute Interrupt Delay */
3748c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
3758c2ecf20Sopenharmony_ci			.type = range_option,
3768c2ecf20Sopenharmony_ci			.name = "Transmit Absolute Interrupt Delay",
3778c2ecf20Sopenharmony_ci			.err  = "using default of " __MODULE_STRING(DEFAULT_TADV),
3788c2ecf20Sopenharmony_ci			.def  = DEFAULT_TADV,
3798c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_TXABSDELAY,
3808c2ecf20Sopenharmony_ci					 .max = MAX_TXABSDELAY }}
3818c2ecf20Sopenharmony_ci		};
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		if (num_TxAbsIntDelay > bd) {
3848c2ecf20Sopenharmony_ci			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
3858c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
3868c2ecf20Sopenharmony_ci					      adapter);
3878c2ecf20Sopenharmony_ci		} else {
3888c2ecf20Sopenharmony_ci			adapter->tx_abs_int_delay = opt.def;
3898c2ecf20Sopenharmony_ci		}
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci	{ /* Receive Interrupt Delay */
3928c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
3938c2ecf20Sopenharmony_ci			.type = range_option,
3948c2ecf20Sopenharmony_ci			.name = "Receive Interrupt Delay",
3958c2ecf20Sopenharmony_ci			.err  = "using default of " __MODULE_STRING(DEFAULT_RDTR),
3968c2ecf20Sopenharmony_ci			.def  = DEFAULT_RDTR,
3978c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_RXDELAY,
3988c2ecf20Sopenharmony_ci					 .max = MAX_RXDELAY }}
3998c2ecf20Sopenharmony_ci		};
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		if (num_RxIntDelay > bd) {
4028c2ecf20Sopenharmony_ci			adapter->rx_int_delay = RxIntDelay[bd];
4038c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->rx_int_delay, &opt,
4048c2ecf20Sopenharmony_ci					      adapter);
4058c2ecf20Sopenharmony_ci		} else {
4068c2ecf20Sopenharmony_ci			adapter->rx_int_delay = opt.def;
4078c2ecf20Sopenharmony_ci		}
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci	{ /* Receive Absolute Interrupt Delay */
4108c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
4118c2ecf20Sopenharmony_ci			.type = range_option,
4128c2ecf20Sopenharmony_ci			.name = "Receive Absolute Interrupt Delay",
4138c2ecf20Sopenharmony_ci			.err  = "using default of " __MODULE_STRING(DEFAULT_RADV),
4148c2ecf20Sopenharmony_ci			.def  = DEFAULT_RADV,
4158c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_RXABSDELAY,
4168c2ecf20Sopenharmony_ci					 .max = MAX_RXABSDELAY }}
4178c2ecf20Sopenharmony_ci		};
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci		if (num_RxAbsIntDelay > bd) {
4208c2ecf20Sopenharmony_ci			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
4218c2ecf20Sopenharmony_ci			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
4228c2ecf20Sopenharmony_ci					      adapter);
4238c2ecf20Sopenharmony_ci		} else {
4248c2ecf20Sopenharmony_ci			adapter->rx_abs_int_delay = opt.def;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci	{ /* Interrupt Throttling Rate */
4288c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
4298c2ecf20Sopenharmony_ci			.type = range_option,
4308c2ecf20Sopenharmony_ci			.name = "Interrupt Throttling Rate (ints/sec)",
4318c2ecf20Sopenharmony_ci			.err  = "using default of " __MODULE_STRING(DEFAULT_ITR),
4328c2ecf20Sopenharmony_ci			.def  = DEFAULT_ITR,
4338c2ecf20Sopenharmony_ci			.arg  = { .r = { .min = MIN_ITR,
4348c2ecf20Sopenharmony_ci					 .max = MAX_ITR }}
4358c2ecf20Sopenharmony_ci		};
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		if (num_InterruptThrottleRate > bd) {
4388c2ecf20Sopenharmony_ci			adapter->itr = InterruptThrottleRate[bd];
4398c2ecf20Sopenharmony_ci			switch (adapter->itr) {
4408c2ecf20Sopenharmony_ci			case 0:
4418c2ecf20Sopenharmony_ci				e_dev_info("%s turned off\n", opt.name);
4428c2ecf20Sopenharmony_ci				break;
4438c2ecf20Sopenharmony_ci			case 1:
4448c2ecf20Sopenharmony_ci				e_dev_info("%s set to dynamic mode\n",
4458c2ecf20Sopenharmony_ci					   opt.name);
4468c2ecf20Sopenharmony_ci				adapter->itr_setting = adapter->itr;
4478c2ecf20Sopenharmony_ci				adapter->itr = 20000;
4488c2ecf20Sopenharmony_ci				break;
4498c2ecf20Sopenharmony_ci			case 3:
4508c2ecf20Sopenharmony_ci				e_dev_info("%s set to dynamic conservative "
4518c2ecf20Sopenharmony_ci					   "mode\n", opt.name);
4528c2ecf20Sopenharmony_ci				adapter->itr_setting = adapter->itr;
4538c2ecf20Sopenharmony_ci				adapter->itr = 20000;
4548c2ecf20Sopenharmony_ci				break;
4558c2ecf20Sopenharmony_ci			case 4:
4568c2ecf20Sopenharmony_ci				e_dev_info("%s set to simplified "
4578c2ecf20Sopenharmony_ci					   "(2000-8000) ints mode\n", opt.name);
4588c2ecf20Sopenharmony_ci				adapter->itr_setting = adapter->itr;
4598c2ecf20Sopenharmony_ci				break;
4608c2ecf20Sopenharmony_ci			default:
4618c2ecf20Sopenharmony_ci				e1000_validate_option(&adapter->itr, &opt,
4628c2ecf20Sopenharmony_ci						      adapter);
4638c2ecf20Sopenharmony_ci				/* save the setting, because the dynamic bits
4648c2ecf20Sopenharmony_ci				 * change itr.
4658c2ecf20Sopenharmony_ci				 * clear the lower two bits because they are
4668c2ecf20Sopenharmony_ci				 * used as control
4678c2ecf20Sopenharmony_ci				 */
4688c2ecf20Sopenharmony_ci				adapter->itr_setting = adapter->itr & ~3;
4698c2ecf20Sopenharmony_ci				break;
4708c2ecf20Sopenharmony_ci			}
4718c2ecf20Sopenharmony_ci		} else {
4728c2ecf20Sopenharmony_ci			adapter->itr_setting = opt.def;
4738c2ecf20Sopenharmony_ci			adapter->itr = 20000;
4748c2ecf20Sopenharmony_ci		}
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci	{ /* Smart Power Down */
4778c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
4788c2ecf20Sopenharmony_ci			.type = enable_option,
4798c2ecf20Sopenharmony_ci			.name = "PHY Smart Power Down",
4808c2ecf20Sopenharmony_ci			.err  = "defaulting to Disabled",
4818c2ecf20Sopenharmony_ci			.def  = OPTION_DISABLED
4828c2ecf20Sopenharmony_ci		};
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci		if (num_SmartPowerDownEnable > bd) {
4858c2ecf20Sopenharmony_ci			unsigned int spd = SmartPowerDownEnable[bd];
4868c2ecf20Sopenharmony_ci			e1000_validate_option(&spd, &opt, adapter);
4878c2ecf20Sopenharmony_ci			adapter->smart_power_down = spd;
4888c2ecf20Sopenharmony_ci		} else {
4898c2ecf20Sopenharmony_ci			adapter->smart_power_down = opt.def;
4908c2ecf20Sopenharmony_ci		}
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	switch (adapter->hw.media_type) {
4948c2ecf20Sopenharmony_ci	case e1000_media_type_fiber:
4958c2ecf20Sopenharmony_ci	case e1000_media_type_internal_serdes:
4968c2ecf20Sopenharmony_ci		e1000_check_fiber_options(adapter);
4978c2ecf20Sopenharmony_ci		break;
4988c2ecf20Sopenharmony_ci	case e1000_media_type_copper:
4998c2ecf20Sopenharmony_ci		e1000_check_copper_options(adapter);
5008c2ecf20Sopenharmony_ci		break;
5018c2ecf20Sopenharmony_ci	default:
5028c2ecf20Sopenharmony_ci		BUG();
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci/**
5078c2ecf20Sopenharmony_ci * e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
5088c2ecf20Sopenharmony_ci * @adapter: board private structure
5098c2ecf20Sopenharmony_ci *
5108c2ecf20Sopenharmony_ci * Handles speed and duplex options on fiber adapters
5118c2ecf20Sopenharmony_ci **/
5128c2ecf20Sopenharmony_cistatic void e1000_check_fiber_options(struct e1000_adapter *adapter)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	int bd = adapter->bd_number;
5158c2ecf20Sopenharmony_ci	if (num_Speed > bd) {
5168c2ecf20Sopenharmony_ci		e_dev_info("Speed not valid for fiber adapters, parameter "
5178c2ecf20Sopenharmony_ci			   "ignored\n");
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	if (num_Duplex > bd) {
5218c2ecf20Sopenharmony_ci		e_dev_info("Duplex not valid for fiber adapters, parameter "
5228c2ecf20Sopenharmony_ci			   "ignored\n");
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
5268c2ecf20Sopenharmony_ci		e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
5278c2ecf20Sopenharmony_ci			   "adapters, parameter ignored\n");
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci/**
5328c2ecf20Sopenharmony_ci * e1000_check_copper_options - Range Checking for Link Options, Copper Version
5338c2ecf20Sopenharmony_ci * @adapter: board private structure
5348c2ecf20Sopenharmony_ci *
5358c2ecf20Sopenharmony_ci * Handles speed and duplex options on copper adapters
5368c2ecf20Sopenharmony_ci **/
5378c2ecf20Sopenharmony_cistatic void e1000_check_copper_options(struct e1000_adapter *adapter)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	struct e1000_option opt;
5408c2ecf20Sopenharmony_ci	unsigned int speed, dplx, an;
5418c2ecf20Sopenharmony_ci	int bd = adapter->bd_number;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	{ /* Speed */
5448c2ecf20Sopenharmony_ci		static const struct e1000_opt_list speed_list[] = {
5458c2ecf20Sopenharmony_ci			{          0, "" },
5468c2ecf20Sopenharmony_ci			{   SPEED_10, "" },
5478c2ecf20Sopenharmony_ci			{  SPEED_100, "" },
5488c2ecf20Sopenharmony_ci			{ SPEED_1000, "" }};
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
5518c2ecf20Sopenharmony_ci			.type = list_option,
5528c2ecf20Sopenharmony_ci			.name = "Speed",
5538c2ecf20Sopenharmony_ci			.err  = "parameter ignored",
5548c2ecf20Sopenharmony_ci			.def  = 0,
5558c2ecf20Sopenharmony_ci			.arg  = { .l = { .nr = ARRAY_SIZE(speed_list),
5568c2ecf20Sopenharmony_ci					 .p = speed_list }}
5578c2ecf20Sopenharmony_ci		};
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci		if (num_Speed > bd) {
5608c2ecf20Sopenharmony_ci			speed = Speed[bd];
5618c2ecf20Sopenharmony_ci			e1000_validate_option(&speed, &opt, adapter);
5628c2ecf20Sopenharmony_ci		} else {
5638c2ecf20Sopenharmony_ci			speed = opt.def;
5648c2ecf20Sopenharmony_ci		}
5658c2ecf20Sopenharmony_ci	}
5668c2ecf20Sopenharmony_ci	{ /* Duplex */
5678c2ecf20Sopenharmony_ci		static const struct e1000_opt_list dplx_list[] = {
5688c2ecf20Sopenharmony_ci			{           0, "" },
5698c2ecf20Sopenharmony_ci			{ HALF_DUPLEX, "" },
5708c2ecf20Sopenharmony_ci			{ FULL_DUPLEX, "" }};
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
5738c2ecf20Sopenharmony_ci			.type = list_option,
5748c2ecf20Sopenharmony_ci			.name = "Duplex",
5758c2ecf20Sopenharmony_ci			.err  = "parameter ignored",
5768c2ecf20Sopenharmony_ci			.def  = 0,
5778c2ecf20Sopenharmony_ci			.arg  = { .l = { .nr = ARRAY_SIZE(dplx_list),
5788c2ecf20Sopenharmony_ci					 .p = dplx_list }}
5798c2ecf20Sopenharmony_ci		};
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci		if (num_Duplex > bd) {
5828c2ecf20Sopenharmony_ci			dplx = Duplex[bd];
5838c2ecf20Sopenharmony_ci			e1000_validate_option(&dplx, &opt, adapter);
5848c2ecf20Sopenharmony_ci		} else {
5858c2ecf20Sopenharmony_ci			dplx = opt.def;
5868c2ecf20Sopenharmony_ci		}
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
5908c2ecf20Sopenharmony_ci		e_dev_info("AutoNeg specified along with Speed or Duplex, "
5918c2ecf20Sopenharmony_ci			   "parameter ignored\n");
5928c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
5938c2ecf20Sopenharmony_ci	} else { /* Autoneg */
5948c2ecf20Sopenharmony_ci		static const struct e1000_opt_list an_list[] =
5958c2ecf20Sopenharmony_ci			#define AA "AutoNeg advertising "
5968c2ecf20Sopenharmony_ci			{{ 0x01, AA "10/HD" },
5978c2ecf20Sopenharmony_ci			 { 0x02, AA "10/FD" },
5988c2ecf20Sopenharmony_ci			 { 0x03, AA "10/FD, 10/HD" },
5998c2ecf20Sopenharmony_ci			 { 0x04, AA "100/HD" },
6008c2ecf20Sopenharmony_ci			 { 0x05, AA "100/HD, 10/HD" },
6018c2ecf20Sopenharmony_ci			 { 0x06, AA "100/HD, 10/FD" },
6028c2ecf20Sopenharmony_ci			 { 0x07, AA "100/HD, 10/FD, 10/HD" },
6038c2ecf20Sopenharmony_ci			 { 0x08, AA "100/FD" },
6048c2ecf20Sopenharmony_ci			 { 0x09, AA "100/FD, 10/HD" },
6058c2ecf20Sopenharmony_ci			 { 0x0a, AA "100/FD, 10/FD" },
6068c2ecf20Sopenharmony_ci			 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
6078c2ecf20Sopenharmony_ci			 { 0x0c, AA "100/FD, 100/HD" },
6088c2ecf20Sopenharmony_ci			 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
6098c2ecf20Sopenharmony_ci			 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
6108c2ecf20Sopenharmony_ci			 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
6118c2ecf20Sopenharmony_ci			 { 0x20, AA "1000/FD" },
6128c2ecf20Sopenharmony_ci			 { 0x21, AA "1000/FD, 10/HD" },
6138c2ecf20Sopenharmony_ci			 { 0x22, AA "1000/FD, 10/FD" },
6148c2ecf20Sopenharmony_ci			 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
6158c2ecf20Sopenharmony_ci			 { 0x24, AA "1000/FD, 100/HD" },
6168c2ecf20Sopenharmony_ci			 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
6178c2ecf20Sopenharmony_ci			 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
6188c2ecf20Sopenharmony_ci			 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
6198c2ecf20Sopenharmony_ci			 { 0x28, AA "1000/FD, 100/FD" },
6208c2ecf20Sopenharmony_ci			 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
6218c2ecf20Sopenharmony_ci			 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
6228c2ecf20Sopenharmony_ci			 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
6238c2ecf20Sopenharmony_ci			 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
6248c2ecf20Sopenharmony_ci			 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
6258c2ecf20Sopenharmony_ci			 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
6268c2ecf20Sopenharmony_ci			 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		opt = (struct e1000_option) {
6298c2ecf20Sopenharmony_ci			.type = list_option,
6308c2ecf20Sopenharmony_ci			.name = "AutoNeg",
6318c2ecf20Sopenharmony_ci			.err  = "parameter ignored",
6328c2ecf20Sopenharmony_ci			.def  = AUTONEG_ADV_DEFAULT,
6338c2ecf20Sopenharmony_ci			.arg  = { .l = { .nr = ARRAY_SIZE(an_list),
6348c2ecf20Sopenharmony_ci					 .p = an_list }}
6358c2ecf20Sopenharmony_ci		};
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci		if (num_AutoNeg > bd) {
6388c2ecf20Sopenharmony_ci			an = AutoNeg[bd];
6398c2ecf20Sopenharmony_ci			e1000_validate_option(&an, &opt, adapter);
6408c2ecf20Sopenharmony_ci		} else {
6418c2ecf20Sopenharmony_ci			an = opt.def;
6428c2ecf20Sopenharmony_ci		}
6438c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = an;
6448c2ecf20Sopenharmony_ci	}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	switch (speed + dplx) {
6478c2ecf20Sopenharmony_ci	case 0:
6488c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 1;
6498c2ecf20Sopenharmony_ci		if ((num_Speed > bd) && (speed != 0 || dplx != 0))
6508c2ecf20Sopenharmony_ci			e_dev_info("Speed and duplex autonegotiation "
6518c2ecf20Sopenharmony_ci				   "enabled\n");
6528c2ecf20Sopenharmony_ci		break;
6538c2ecf20Sopenharmony_ci	case HALF_DUPLEX:
6548c2ecf20Sopenharmony_ci		e_dev_info("Half Duplex specified without Speed\n");
6558c2ecf20Sopenharmony_ci		e_dev_info("Using Autonegotiation at Half Duplex only\n");
6568c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 1;
6578c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
6588c2ecf20Sopenharmony_ci						 ADVERTISE_100_HALF;
6598c2ecf20Sopenharmony_ci		break;
6608c2ecf20Sopenharmony_ci	case FULL_DUPLEX:
6618c2ecf20Sopenharmony_ci		e_dev_info("Full Duplex specified without Speed\n");
6628c2ecf20Sopenharmony_ci		e_dev_info("Using Autonegotiation at Full Duplex only\n");
6638c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 1;
6648c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
6658c2ecf20Sopenharmony_ci						 ADVERTISE_100_FULL |
6668c2ecf20Sopenharmony_ci						 ADVERTISE_1000_FULL;
6678c2ecf20Sopenharmony_ci		break;
6688c2ecf20Sopenharmony_ci	case SPEED_10:
6698c2ecf20Sopenharmony_ci		e_dev_info("10 Mbps Speed specified without Duplex\n");
6708c2ecf20Sopenharmony_ci		e_dev_info("Using Autonegotiation at 10 Mbps only\n");
6718c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 1;
6728c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
6738c2ecf20Sopenharmony_ci						 ADVERTISE_10_FULL;
6748c2ecf20Sopenharmony_ci		break;
6758c2ecf20Sopenharmony_ci	case SPEED_10 + HALF_DUPLEX:
6768c2ecf20Sopenharmony_ci		e_dev_info("Forcing to 10 Mbps Half Duplex\n");
6778c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 0;
6788c2ecf20Sopenharmony_ci		adapter->hw.forced_speed_duplex = e1000_10_half;
6798c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = 0;
6808c2ecf20Sopenharmony_ci		break;
6818c2ecf20Sopenharmony_ci	case SPEED_10 + FULL_DUPLEX:
6828c2ecf20Sopenharmony_ci		e_dev_info("Forcing to 10 Mbps Full Duplex\n");
6838c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 0;
6848c2ecf20Sopenharmony_ci		adapter->hw.forced_speed_duplex = e1000_10_full;
6858c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = 0;
6868c2ecf20Sopenharmony_ci		break;
6878c2ecf20Sopenharmony_ci	case SPEED_100:
6888c2ecf20Sopenharmony_ci		e_dev_info("100 Mbps Speed specified without Duplex\n");
6898c2ecf20Sopenharmony_ci		e_dev_info("Using Autonegotiation at 100 Mbps only\n");
6908c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 1;
6918c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
6928c2ecf20Sopenharmony_ci						 ADVERTISE_100_FULL;
6938c2ecf20Sopenharmony_ci		break;
6948c2ecf20Sopenharmony_ci	case SPEED_100 + HALF_DUPLEX:
6958c2ecf20Sopenharmony_ci		e_dev_info("Forcing to 100 Mbps Half Duplex\n");
6968c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 0;
6978c2ecf20Sopenharmony_ci		adapter->hw.forced_speed_duplex = e1000_100_half;
6988c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = 0;
6998c2ecf20Sopenharmony_ci		break;
7008c2ecf20Sopenharmony_ci	case SPEED_100 + FULL_DUPLEX:
7018c2ecf20Sopenharmony_ci		e_dev_info("Forcing to 100 Mbps Full Duplex\n");
7028c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 0;
7038c2ecf20Sopenharmony_ci		adapter->hw.forced_speed_duplex = e1000_100_full;
7048c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = 0;
7058c2ecf20Sopenharmony_ci		break;
7068c2ecf20Sopenharmony_ci	case SPEED_1000:
7078c2ecf20Sopenharmony_ci		e_dev_info("1000 Mbps Speed specified without Duplex\n");
7088c2ecf20Sopenharmony_ci		goto full_duplex_only;
7098c2ecf20Sopenharmony_ci	case SPEED_1000 + HALF_DUPLEX:
7108c2ecf20Sopenharmony_ci		e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
7118c2ecf20Sopenharmony_ci		fallthrough;
7128c2ecf20Sopenharmony_ci	case SPEED_1000 + FULL_DUPLEX:
7138c2ecf20Sopenharmony_cifull_duplex_only:
7148c2ecf20Sopenharmony_ci		e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
7158c2ecf20Sopenharmony_ci			   "only\n");
7168c2ecf20Sopenharmony_ci		adapter->hw.autoneg = adapter->fc_autoneg = 1;
7178c2ecf20Sopenharmony_ci		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
7188c2ecf20Sopenharmony_ci		break;
7198c2ecf20Sopenharmony_ci	default:
7208c2ecf20Sopenharmony_ci		BUG();
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
7248c2ecf20Sopenharmony_ci	if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
7258c2ecf20Sopenharmony_ci		e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
7268c2ecf20Sopenharmony_ci			   "Setting MDI-X to a compatible value.\n");
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
730