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