cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pch_gbe_param.c (14931B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 1999 - 2010 Intel Corporation.
      4 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
      5 *
      6 * This code was derived from the Intel e1000e Linux driver.
      7 */
      8
      9#include "pch_gbe.h"
     10#include <linux/module.h>	/* for __MODULE_STRING */
     11
     12#define OPTION_UNSET   -1
     13#define OPTION_DISABLED 0
     14#define OPTION_ENABLED  1
     15
     16/*
     17 * TxDescriptors - Transmit Descriptor Count
     18 * @Valid Range:   PCH_GBE_MIN_TXD - PCH_GBE_MAX_TXD
     19 * @Default Value: PCH_GBE_DEFAULT_TXD
     20 */
     21static int TxDescriptors = OPTION_UNSET;
     22module_param(TxDescriptors, int, 0);
     23MODULE_PARM_DESC(TxDescriptors, "Number of transmit descriptors");
     24
     25/*
     26 * RxDescriptors -Receive Descriptor Count
     27 * @Valid Range:   PCH_GBE_MIN_RXD - PCH_GBE_MAX_RXD
     28 * @Default Value: PCH_GBE_DEFAULT_RXD
     29 */
     30static int RxDescriptors = OPTION_UNSET;
     31module_param(RxDescriptors, int, 0);
     32MODULE_PARM_DESC(RxDescriptors, "Number of receive descriptors");
     33
     34/*
     35 * Speed - User Specified Speed Override
     36 * @Valid Range: 0, 10, 100, 1000
     37 *   - 0:    auto-negotiate at all supported speeds
     38 *   - 10:   only link at 10 Mbps
     39 *   - 100:  only link at 100 Mbps
     40 *   - 1000: only link at 1000 Mbps
     41 * @Default Value: 0
     42 */
     43static int Speed = OPTION_UNSET;
     44module_param(Speed, int, 0);
     45MODULE_PARM_DESC(Speed, "Speed setting");
     46
     47/*
     48 * Duplex - User Specified Duplex Override
     49 * @Valid Range: 0-2
     50 *   - 0:  auto-negotiate for duplex
     51 *   - 1:  only link at half duplex
     52 *   - 2:  only link at full duplex
     53 * @Default Value: 0
     54 */
     55static int Duplex = OPTION_UNSET;
     56module_param(Duplex, int, 0);
     57MODULE_PARM_DESC(Duplex, "Duplex setting");
     58
     59#define HALF_DUPLEX 1
     60#define FULL_DUPLEX 2
     61
     62/*
     63 * AutoNeg - Auto-negotiation Advertisement Override
     64 * @Valid Range: 0x01-0x0F, 0x20-0x2F
     65 *
     66 *       The AutoNeg value is a bit mask describing which speed and duplex
     67 *       combinations should be advertised during auto-negotiation.
     68 *       The supported speed and duplex modes are listed below
     69 *
     70 *       Bit           7     6     5      4      3     2     1      0
     71 *       Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
     72 *       Duplex                    Full          Full  Half  Full   Half
     73 *
     74 * @Default Value: 0x2F (copper)
     75 */
     76static int AutoNeg = OPTION_UNSET;
     77module_param(AutoNeg, int, 0);
     78MODULE_PARM_DESC(AutoNeg, "Advertised auto-negotiation setting");
     79
     80#define PHY_ADVERTISE_10_HALF      0x0001
     81#define PHY_ADVERTISE_10_FULL      0x0002
     82#define PHY_ADVERTISE_100_HALF     0x0004
     83#define PHY_ADVERTISE_100_FULL     0x0008
     84#define PHY_ADVERTISE_1000_HALF    0x0010 /* Not used, just FYI */
     85#define PHY_ADVERTISE_1000_FULL    0x0020
     86#define PCH_AUTONEG_ADVERTISE_DEFAULT   0x2F
     87
     88/*
     89 * FlowControl - User Specified Flow Control Override
     90 * @Valid Range: 0-3
     91 *    - 0:  No Flow Control
     92 *    - 1:  Rx only, respond to PAUSE frames but do not generate them
     93 *    - 2:  Tx only, generate PAUSE frames but ignore them on receive
     94 *    - 3:  Full Flow Control Support
     95 * @Default Value: Read flow control settings from the EEPROM
     96 */
     97static int FlowControl = OPTION_UNSET;
     98module_param(FlowControl, int, 0);
     99MODULE_PARM_DESC(FlowControl, "Flow Control setting");
    100
    101/*
    102 * XsumRX - Receive Checksum Offload Enable/Disable
    103 * @Valid Range: 0, 1
    104 *    - 0:  disables all checksum offload
    105 *    - 1:  enables receive IP/TCP/UDP checksum offload
    106 * @Default Value: PCH_GBE_DEFAULT_RX_CSUM
    107 */
    108static int XsumRX = OPTION_UNSET;
    109module_param(XsumRX, int, 0);
    110MODULE_PARM_DESC(XsumRX, "Disable or enable Receive Checksum offload");
    111
    112#define PCH_GBE_DEFAULT_RX_CSUM             true	/* trueorfalse */
    113
    114/*
    115 * XsumTX - Transmit Checksum Offload Enable/Disable
    116 * @Valid Range: 0, 1
    117 *    - 0:  disables all checksum offload
    118 *    - 1:  enables transmit IP/TCP/UDP checksum offload
    119 * @Default Value: PCH_GBE_DEFAULT_TX_CSUM
    120 */
    121static int XsumTX = OPTION_UNSET;
    122module_param(XsumTX, int, 0);
    123MODULE_PARM_DESC(XsumTX, "Disable or enable Transmit Checksum offload");
    124
    125#define PCH_GBE_DEFAULT_TX_CSUM             true	/* trueorfalse */
    126
    127/*
    128 * pch_gbe_option - Force the MAC's flow control settings
    129 * @hw:	            Pointer to the HW structure
    130 * Returns:
    131 *	0:			Successful.
    132 *	Negative value:		Failed.
    133 */
    134struct pch_gbe_option {
    135	enum { enable_option, range_option, list_option } type;
    136	char *name;
    137	char *err;
    138	int  def;
    139	union {
    140		struct { /* range_option info */
    141			int min;
    142			int max;
    143		} r;
    144		struct { /* list_option info */
    145			int nr;
    146			const struct pch_gbe_opt_list { int i; char *str; } *p;
    147		} l;
    148	} arg;
    149};
    150
    151static const struct pch_gbe_opt_list speed_list[] = {
    152	{ 0, "" },
    153	{ SPEED_10, "" },
    154	{ SPEED_100, "" },
    155	{ SPEED_1000, "" }
    156};
    157
    158static const struct pch_gbe_opt_list dplx_list[] = {
    159	{ 0, "" },
    160	{ HALF_DUPLEX, "" },
    161	{ FULL_DUPLEX, "" }
    162};
    163
    164static const struct pch_gbe_opt_list an_list[] =
    165	#define AA "AutoNeg advertising "
    166	{{ 0x01, AA "10/HD" },
    167	 { 0x02, AA "10/FD" },
    168	 { 0x03, AA "10/FD, 10/HD" },
    169	 { 0x04, AA "100/HD" },
    170	 { 0x05, AA "100/HD, 10/HD" },
    171	 { 0x06, AA "100/HD, 10/FD" },
    172	 { 0x07, AA "100/HD, 10/FD, 10/HD" },
    173	 { 0x08, AA "100/FD" },
    174	 { 0x09, AA "100/FD, 10/HD" },
    175	 { 0x0a, AA "100/FD, 10/FD" },
    176	 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
    177	 { 0x0c, AA "100/FD, 100/HD" },
    178	 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
    179	 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
    180	 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
    181	 { 0x20, AA "1000/FD" },
    182	 { 0x21, AA "1000/FD, 10/HD" },
    183	 { 0x22, AA "1000/FD, 10/FD" },
    184	 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
    185	 { 0x24, AA "1000/FD, 100/HD" },
    186	 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
    187	 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
    188	 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
    189	 { 0x28, AA "1000/FD, 100/FD" },
    190	 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
    191	 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
    192	 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
    193	 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
    194	 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
    195	 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
    196	 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }
    197};
    198
    199static const struct pch_gbe_opt_list fc_list[] = {
    200	{ PCH_GBE_FC_NONE, "Flow Control Disabled" },
    201	{ PCH_GBE_FC_RX_PAUSE, "Flow Control Receive Only" },
    202	{ PCH_GBE_FC_TX_PAUSE, "Flow Control Transmit Only" },
    203	{ PCH_GBE_FC_FULL, "Flow Control Enabled" }
    204};
    205
    206/**
    207 * pch_gbe_validate_option - Validate option
    208 * @value:    value
    209 * @opt:      option
    210 * @adapter:  Board private structure
    211 * Returns:
    212 *	0:			Successful.
    213 *	Negative value:		Failed.
    214 */
    215static int pch_gbe_validate_option(int *value,
    216				    const struct pch_gbe_option *opt,
    217				    struct pch_gbe_adapter *adapter)
    218{
    219	if (*value == OPTION_UNSET) {
    220		*value = opt->def;
    221		return 0;
    222	}
    223
    224	switch (opt->type) {
    225	case enable_option:
    226		switch (*value) {
    227		case OPTION_ENABLED:
    228			netdev_dbg(adapter->netdev, "%s Enabled\n", opt->name);
    229			return 0;
    230		case OPTION_DISABLED:
    231			netdev_dbg(adapter->netdev, "%s Disabled\n", opt->name);
    232			return 0;
    233		}
    234		break;
    235	case range_option:
    236		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
    237			netdev_dbg(adapter->netdev, "%s set to %i\n",
    238				   opt->name, *value);
    239			return 0;
    240		}
    241		break;
    242	case list_option: {
    243		int i;
    244		const struct pch_gbe_opt_list *ent;
    245
    246		for (i = 0; i < opt->arg.l.nr; i++) {
    247			ent = &opt->arg.l.p[i];
    248			if (*value == ent->i) {
    249				if (ent->str[0] != '\0')
    250					netdev_dbg(adapter->netdev, "%s\n",
    251						   ent->str);
    252				return 0;
    253			}
    254		}
    255	}
    256		break;
    257	default:
    258		BUG();
    259	}
    260
    261	netdev_dbg(adapter->netdev, "Invalid %s value specified (%i) %s\n",
    262		   opt->name, *value, opt->err);
    263	*value = opt->def;
    264	return -1;
    265}
    266
    267/**
    268 * pch_gbe_check_copper_options - Range Checking for Link Options, Copper Version
    269 * @adapter:  Board private structure
    270 */
    271static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
    272{
    273	struct pch_gbe_hw *hw = &adapter->hw;
    274	int speed, dplx;
    275
    276	{ /* Speed */
    277		static const struct pch_gbe_option opt = {
    278			.type = list_option,
    279			.name = "Speed",
    280			.err  = "parameter ignored",
    281			.def  = 0,
    282			.arg  = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
    283					 .p = speed_list } }
    284		};
    285		speed = Speed;
    286		pch_gbe_validate_option(&speed, &opt, adapter);
    287	}
    288	{ /* Duplex */
    289		static const struct pch_gbe_option opt = {
    290			.type = list_option,
    291			.name = "Duplex",
    292			.err  = "parameter ignored",
    293			.def  = 0,
    294			.arg  = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
    295					 .p = dplx_list } }
    296		};
    297		dplx = Duplex;
    298		pch_gbe_validate_option(&dplx, &opt, adapter);
    299	}
    300
    301	{ /* Autoneg */
    302		static const struct pch_gbe_option opt = {
    303			.type = list_option,
    304			.name = "AutoNeg",
    305			.err  = "parameter ignored",
    306			.def  = PCH_AUTONEG_ADVERTISE_DEFAULT,
    307			.arg  = { .l = { .nr = (int)ARRAY_SIZE(an_list),
    308					 .p = an_list} }
    309		};
    310		if (speed || dplx) {
    311			netdev_dbg(adapter->netdev,
    312				   "AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
    313			hw->phy.autoneg_advertised = opt.def;
    314		} else {
    315			int tmp = AutoNeg;
    316
    317			pch_gbe_validate_option(&tmp, &opt, adapter);
    318			hw->phy.autoneg_advertised = tmp;
    319		}
    320	}
    321
    322	switch (speed + dplx) {
    323	case 0:
    324		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
    325		if ((speed || dplx))
    326			netdev_dbg(adapter->netdev,
    327				   "Speed and duplex autonegotiation enabled\n");
    328		hw->mac.link_speed = SPEED_10;
    329		hw->mac.link_duplex = DUPLEX_HALF;
    330		break;
    331	case HALF_DUPLEX:
    332		netdev_dbg(adapter->netdev,
    333			   "Half Duplex specified without Speed\n");
    334		netdev_dbg(adapter->netdev,
    335			   "Using Autonegotiation at Half Duplex only\n");
    336		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
    337		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
    338						PHY_ADVERTISE_100_HALF;
    339		hw->mac.link_speed = SPEED_10;
    340		hw->mac.link_duplex = DUPLEX_HALF;
    341		break;
    342	case FULL_DUPLEX:
    343		netdev_dbg(adapter->netdev,
    344			   "Full Duplex specified without Speed\n");
    345		netdev_dbg(adapter->netdev,
    346			   "Using Autonegotiation at Full Duplex only\n");
    347		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
    348		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
    349						PHY_ADVERTISE_100_FULL |
    350						PHY_ADVERTISE_1000_FULL;
    351		hw->mac.link_speed = SPEED_10;
    352		hw->mac.link_duplex = DUPLEX_FULL;
    353		break;
    354	case SPEED_10:
    355		netdev_dbg(adapter->netdev,
    356			   "10 Mbps Speed specified without Duplex\n");
    357		netdev_dbg(adapter->netdev,
    358			   "Using Autonegotiation at 10 Mbps only\n");
    359		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
    360		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
    361						PHY_ADVERTISE_10_FULL;
    362		hw->mac.link_speed = SPEED_10;
    363		hw->mac.link_duplex = DUPLEX_HALF;
    364		break;
    365	case SPEED_10 + HALF_DUPLEX:
    366		netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Half Duplex\n");
    367		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
    368		hw->phy.autoneg_advertised = 0;
    369		hw->mac.link_speed = SPEED_10;
    370		hw->mac.link_duplex = DUPLEX_HALF;
    371		break;
    372	case SPEED_10 + FULL_DUPLEX:
    373		netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Full Duplex\n");
    374		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
    375		hw->phy.autoneg_advertised = 0;
    376		hw->mac.link_speed = SPEED_10;
    377		hw->mac.link_duplex = DUPLEX_FULL;
    378		break;
    379	case SPEED_100:
    380		netdev_dbg(adapter->netdev,
    381			   "100 Mbps Speed specified without Duplex\n");
    382		netdev_dbg(adapter->netdev,
    383			   "Using Autonegotiation at 100 Mbps only\n");
    384		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
    385		hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
    386						PHY_ADVERTISE_100_FULL;
    387		hw->mac.link_speed = SPEED_100;
    388		hw->mac.link_duplex = DUPLEX_HALF;
    389		break;
    390	case SPEED_100 + HALF_DUPLEX:
    391		netdev_dbg(adapter->netdev,
    392			   "Forcing to 100 Mbps Half Duplex\n");
    393		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
    394		hw->phy.autoneg_advertised = 0;
    395		hw->mac.link_speed = SPEED_100;
    396		hw->mac.link_duplex = DUPLEX_HALF;
    397		break;
    398	case SPEED_100 + FULL_DUPLEX:
    399		netdev_dbg(adapter->netdev,
    400			   "Forcing to 100 Mbps Full Duplex\n");
    401		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
    402		hw->phy.autoneg_advertised = 0;
    403		hw->mac.link_speed = SPEED_100;
    404		hw->mac.link_duplex = DUPLEX_FULL;
    405		break;
    406	case SPEED_1000:
    407		netdev_dbg(adapter->netdev,
    408			   "1000 Mbps Speed specified without Duplex\n");
    409		goto full_duplex_only;
    410	case SPEED_1000 + HALF_DUPLEX:
    411		netdev_dbg(adapter->netdev,
    412			   "Half Duplex is not supported at 1000 Mbps\n");
    413		fallthrough;
    414	case SPEED_1000 + FULL_DUPLEX:
    415full_duplex_only:
    416		netdev_dbg(adapter->netdev,
    417			   "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
    418		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
    419		hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
    420		hw->mac.link_speed = SPEED_1000;
    421		hw->mac.link_duplex = DUPLEX_FULL;
    422		break;
    423	default:
    424		BUG();
    425	}
    426}
    427
    428/**
    429 * pch_gbe_check_options - Range Checking for Command Line Parameters
    430 * @adapter:  Board private structure
    431 */
    432void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
    433{
    434	struct pch_gbe_hw *hw = &adapter->hw;
    435	struct net_device *dev = adapter->netdev;
    436	int val;
    437
    438	{ /* Transmit Descriptor Count */
    439		static const struct pch_gbe_option opt = {
    440			.type = range_option,
    441			.name = "Transmit Descriptors",
    442			.err  = "using default of "
    443				__MODULE_STRING(PCH_GBE_DEFAULT_TXD),
    444			.def  = PCH_GBE_DEFAULT_TXD,
    445			.arg  = { .r = { .min = PCH_GBE_MIN_TXD,
    446					 .max = PCH_GBE_MAX_TXD } }
    447		};
    448		struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
    449		tx_ring->count = TxDescriptors;
    450		pch_gbe_validate_option(&tx_ring->count, &opt, adapter);
    451		tx_ring->count = roundup(tx_ring->count,
    452					PCH_GBE_TX_DESC_MULTIPLE);
    453	}
    454	{ /* Receive Descriptor Count */
    455		static const struct pch_gbe_option opt = {
    456			.type = range_option,
    457			.name = "Receive Descriptors",
    458			.err  = "using default of "
    459				__MODULE_STRING(PCH_GBE_DEFAULT_RXD),
    460			.def  = PCH_GBE_DEFAULT_RXD,
    461			.arg  = { .r = { .min = PCH_GBE_MIN_RXD,
    462					 .max = PCH_GBE_MAX_RXD } }
    463		};
    464		struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
    465		rx_ring->count = RxDescriptors;
    466		pch_gbe_validate_option(&rx_ring->count, &opt, adapter);
    467		rx_ring->count = roundup(rx_ring->count,
    468				PCH_GBE_RX_DESC_MULTIPLE);
    469	}
    470	{ /* Checksum Offload Enable/Disable */
    471		static const struct pch_gbe_option opt = {
    472			.type = enable_option,
    473			.name = "Checksum Offload",
    474			.err  = "defaulting to Enabled",
    475			.def  = PCH_GBE_DEFAULT_RX_CSUM
    476		};
    477		val = XsumRX;
    478		pch_gbe_validate_option(&val, &opt, adapter);
    479		if (!val)
    480			dev->features &= ~NETIF_F_RXCSUM;
    481	}
    482	{ /* Checksum Offload Enable/Disable */
    483		static const struct pch_gbe_option opt = {
    484			.type = enable_option,
    485			.name = "Checksum Offload",
    486			.err  = "defaulting to Enabled",
    487			.def  = PCH_GBE_DEFAULT_TX_CSUM
    488		};
    489		val = XsumTX;
    490		pch_gbe_validate_option(&val, &opt, adapter);
    491		if (!val)
    492			dev->features &= ~NETIF_F_CSUM_MASK;
    493	}
    494	{ /* Flow Control */
    495		static const struct pch_gbe_option opt = {
    496			.type = list_option,
    497			.name = "Flow Control",
    498			.err  = "reading default settings from EEPROM",
    499			.def  = PCH_GBE_FC_DEFAULT,
    500			.arg  = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
    501					 .p = fc_list } }
    502		};
    503		int tmp = FlowControl;
    504
    505		pch_gbe_validate_option(&tmp, &opt, adapter);
    506		hw->mac.fc = tmp;
    507	}
    508
    509	pch_gbe_check_copper_options(adapter);
    510}