0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "pch_gbe.h"
0010 #include <linux/module.h> /* for __MODULE_STRING */
0011
0012 #define OPTION_UNSET -1
0013 #define OPTION_DISABLED 0
0014 #define OPTION_ENABLED 1
0015
0016
0017
0018
0019
0020
0021 static int TxDescriptors = OPTION_UNSET;
0022 module_param(TxDescriptors, int, 0);
0023 MODULE_PARM_DESC(TxDescriptors, "Number of transmit descriptors");
0024
0025
0026
0027
0028
0029
0030 static int RxDescriptors = OPTION_UNSET;
0031 module_param(RxDescriptors, int, 0);
0032 MODULE_PARM_DESC(RxDescriptors, "Number of receive descriptors");
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 static int Speed = OPTION_UNSET;
0044 module_param(Speed, int, 0);
0045 MODULE_PARM_DESC(Speed, "Speed setting");
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 static int Duplex = OPTION_UNSET;
0056 module_param(Duplex, int, 0);
0057 MODULE_PARM_DESC(Duplex, "Duplex setting");
0058
0059 #define HALF_DUPLEX 1
0060 #define FULL_DUPLEX 2
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 static int AutoNeg = OPTION_UNSET;
0077 module_param(AutoNeg, int, 0);
0078 MODULE_PARM_DESC(AutoNeg, "Advertised auto-negotiation setting");
0079
0080 #define PHY_ADVERTISE_10_HALF 0x0001
0081 #define PHY_ADVERTISE_10_FULL 0x0002
0082 #define PHY_ADVERTISE_100_HALF 0x0004
0083 #define PHY_ADVERTISE_100_FULL 0x0008
0084 #define PHY_ADVERTISE_1000_HALF 0x0010
0085 #define PHY_ADVERTISE_1000_FULL 0x0020
0086 #define PCH_AUTONEG_ADVERTISE_DEFAULT 0x2F
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 static int FlowControl = OPTION_UNSET;
0098 module_param(FlowControl, int, 0);
0099 MODULE_PARM_DESC(FlowControl, "Flow Control setting");
0100
0101
0102
0103
0104
0105
0106
0107
0108 static int XsumRX = OPTION_UNSET;
0109 module_param(XsumRX, int, 0);
0110 MODULE_PARM_DESC(XsumRX, "Disable or enable Receive Checksum offload");
0111
0112 #define PCH_GBE_DEFAULT_RX_CSUM true
0113
0114
0115
0116
0117
0118
0119
0120
0121 static int XsumTX = OPTION_UNSET;
0122 module_param(XsumTX, int, 0);
0123 MODULE_PARM_DESC(XsumTX, "Disable or enable Transmit Checksum offload");
0124
0125 #define PCH_GBE_DEFAULT_TX_CSUM true
0126
0127
0128
0129
0130
0131
0132
0133
0134 struct pch_gbe_option {
0135 enum { enable_option, range_option, list_option } type;
0136 char *name;
0137 char *err;
0138 int def;
0139 union {
0140 struct {
0141 int min;
0142 int max;
0143 } r;
0144 struct {
0145 int nr;
0146 const struct pch_gbe_opt_list { int i; char *str; } *p;
0147 } l;
0148 } arg;
0149 };
0150
0151 static const struct pch_gbe_opt_list speed_list[] = {
0152 { 0, "" },
0153 { SPEED_10, "" },
0154 { SPEED_100, "" },
0155 { SPEED_1000, "" }
0156 };
0157
0158 static const struct pch_gbe_opt_list dplx_list[] = {
0159 { 0, "" },
0160 { HALF_DUPLEX, "" },
0161 { FULL_DUPLEX, "" }
0162 };
0163
0164 static const struct pch_gbe_opt_list an_list[] =
0165 #define AA "AutoNeg advertising "
0166 {{ 0x01, AA "10/HD" },
0167 { 0x02, AA "10/FD" },
0168 { 0x03, AA "10/FD, 10/HD" },
0169 { 0x04, AA "100/HD" },
0170 { 0x05, AA "100/HD, 10/HD" },
0171 { 0x06, AA "100/HD, 10/FD" },
0172 { 0x07, AA "100/HD, 10/FD, 10/HD" },
0173 { 0x08, AA "100/FD" },
0174 { 0x09, AA "100/FD, 10/HD" },
0175 { 0x0a, AA "100/FD, 10/FD" },
0176 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
0177 { 0x0c, AA "100/FD, 100/HD" },
0178 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
0179 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
0180 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
0181 { 0x20, AA "1000/FD" },
0182 { 0x21, AA "1000/FD, 10/HD" },
0183 { 0x22, AA "1000/FD, 10/FD" },
0184 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
0185 { 0x24, AA "1000/FD, 100/HD" },
0186 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
0187 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
0188 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
0189 { 0x28, AA "1000/FD, 100/FD" },
0190 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
0191 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
0192 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
0193 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
0194 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
0195 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
0196 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }
0197 };
0198
0199 static const struct pch_gbe_opt_list fc_list[] = {
0200 { PCH_GBE_FC_NONE, "Flow Control Disabled" },
0201 { PCH_GBE_FC_RX_PAUSE, "Flow Control Receive Only" },
0202 { PCH_GBE_FC_TX_PAUSE, "Flow Control Transmit Only" },
0203 { PCH_GBE_FC_FULL, "Flow Control Enabled" }
0204 };
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 static int pch_gbe_validate_option(int *value,
0216 const struct pch_gbe_option *opt,
0217 struct pch_gbe_adapter *adapter)
0218 {
0219 if (*value == OPTION_UNSET) {
0220 *value = opt->def;
0221 return 0;
0222 }
0223
0224 switch (opt->type) {
0225 case enable_option:
0226 switch (*value) {
0227 case OPTION_ENABLED:
0228 netdev_dbg(adapter->netdev, "%s Enabled\n", opt->name);
0229 return 0;
0230 case OPTION_DISABLED:
0231 netdev_dbg(adapter->netdev, "%s Disabled\n", opt->name);
0232 return 0;
0233 }
0234 break;
0235 case range_option:
0236 if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
0237 netdev_dbg(adapter->netdev, "%s set to %i\n",
0238 opt->name, *value);
0239 return 0;
0240 }
0241 break;
0242 case list_option: {
0243 int i;
0244 const struct pch_gbe_opt_list *ent;
0245
0246 for (i = 0; i < opt->arg.l.nr; i++) {
0247 ent = &opt->arg.l.p[i];
0248 if (*value == ent->i) {
0249 if (ent->str[0] != '\0')
0250 netdev_dbg(adapter->netdev, "%s\n",
0251 ent->str);
0252 return 0;
0253 }
0254 }
0255 }
0256 break;
0257 default:
0258 BUG();
0259 }
0260
0261 netdev_dbg(adapter->netdev, "Invalid %s value specified (%i) %s\n",
0262 opt->name, *value, opt->err);
0263 *value = opt->def;
0264 return -1;
0265 }
0266
0267
0268
0269
0270
0271 static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
0272 {
0273 struct pch_gbe_hw *hw = &adapter->hw;
0274 int speed, dplx;
0275
0276 {
0277 static const struct pch_gbe_option opt = {
0278 .type = list_option,
0279 .name = "Speed",
0280 .err = "parameter ignored",
0281 .def = 0,
0282 .arg = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
0283 .p = speed_list } }
0284 };
0285 speed = Speed;
0286 pch_gbe_validate_option(&speed, &opt, adapter);
0287 }
0288 {
0289 static const struct pch_gbe_option opt = {
0290 .type = list_option,
0291 .name = "Duplex",
0292 .err = "parameter ignored",
0293 .def = 0,
0294 .arg = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
0295 .p = dplx_list } }
0296 };
0297 dplx = Duplex;
0298 pch_gbe_validate_option(&dplx, &opt, adapter);
0299 }
0300
0301 {
0302 static const struct pch_gbe_option opt = {
0303 .type = list_option,
0304 .name = "AutoNeg",
0305 .err = "parameter ignored",
0306 .def = PCH_AUTONEG_ADVERTISE_DEFAULT,
0307 .arg = { .l = { .nr = (int)ARRAY_SIZE(an_list),
0308 .p = an_list} }
0309 };
0310 if (speed || dplx) {
0311 netdev_dbg(adapter->netdev,
0312 "AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
0313 hw->phy.autoneg_advertised = opt.def;
0314 } else {
0315 int tmp = AutoNeg;
0316
0317 pch_gbe_validate_option(&tmp, &opt, adapter);
0318 hw->phy.autoneg_advertised = tmp;
0319 }
0320 }
0321
0322 switch (speed + dplx) {
0323 case 0:
0324 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
0325 if ((speed || dplx))
0326 netdev_dbg(adapter->netdev,
0327 "Speed and duplex autonegotiation enabled\n");
0328 hw->mac.link_speed = SPEED_10;
0329 hw->mac.link_duplex = DUPLEX_HALF;
0330 break;
0331 case HALF_DUPLEX:
0332 netdev_dbg(adapter->netdev,
0333 "Half Duplex specified without Speed\n");
0334 netdev_dbg(adapter->netdev,
0335 "Using Autonegotiation at Half Duplex only\n");
0336 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
0337 hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
0338 PHY_ADVERTISE_100_HALF;
0339 hw->mac.link_speed = SPEED_10;
0340 hw->mac.link_duplex = DUPLEX_HALF;
0341 break;
0342 case FULL_DUPLEX:
0343 netdev_dbg(adapter->netdev,
0344 "Full Duplex specified without Speed\n");
0345 netdev_dbg(adapter->netdev,
0346 "Using Autonegotiation at Full Duplex only\n");
0347 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
0348 hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
0349 PHY_ADVERTISE_100_FULL |
0350 PHY_ADVERTISE_1000_FULL;
0351 hw->mac.link_speed = SPEED_10;
0352 hw->mac.link_duplex = DUPLEX_FULL;
0353 break;
0354 case SPEED_10:
0355 netdev_dbg(adapter->netdev,
0356 "10 Mbps Speed specified without Duplex\n");
0357 netdev_dbg(adapter->netdev,
0358 "Using Autonegotiation at 10 Mbps only\n");
0359 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
0360 hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
0361 PHY_ADVERTISE_10_FULL;
0362 hw->mac.link_speed = SPEED_10;
0363 hw->mac.link_duplex = DUPLEX_HALF;
0364 break;
0365 case SPEED_10 + HALF_DUPLEX:
0366 netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Half Duplex\n");
0367 hw->mac.autoneg = hw->mac.fc_autoneg = 0;
0368 hw->phy.autoneg_advertised = 0;
0369 hw->mac.link_speed = SPEED_10;
0370 hw->mac.link_duplex = DUPLEX_HALF;
0371 break;
0372 case SPEED_10 + FULL_DUPLEX:
0373 netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Full Duplex\n");
0374 hw->mac.autoneg = hw->mac.fc_autoneg = 0;
0375 hw->phy.autoneg_advertised = 0;
0376 hw->mac.link_speed = SPEED_10;
0377 hw->mac.link_duplex = DUPLEX_FULL;
0378 break;
0379 case SPEED_100:
0380 netdev_dbg(adapter->netdev,
0381 "100 Mbps Speed specified without Duplex\n");
0382 netdev_dbg(adapter->netdev,
0383 "Using Autonegotiation at 100 Mbps only\n");
0384 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
0385 hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
0386 PHY_ADVERTISE_100_FULL;
0387 hw->mac.link_speed = SPEED_100;
0388 hw->mac.link_duplex = DUPLEX_HALF;
0389 break;
0390 case SPEED_100 + HALF_DUPLEX:
0391 netdev_dbg(adapter->netdev,
0392 "Forcing to 100 Mbps Half Duplex\n");
0393 hw->mac.autoneg = hw->mac.fc_autoneg = 0;
0394 hw->phy.autoneg_advertised = 0;
0395 hw->mac.link_speed = SPEED_100;
0396 hw->mac.link_duplex = DUPLEX_HALF;
0397 break;
0398 case SPEED_100 + FULL_DUPLEX:
0399 netdev_dbg(adapter->netdev,
0400 "Forcing to 100 Mbps Full Duplex\n");
0401 hw->mac.autoneg = hw->mac.fc_autoneg = 0;
0402 hw->phy.autoneg_advertised = 0;
0403 hw->mac.link_speed = SPEED_100;
0404 hw->mac.link_duplex = DUPLEX_FULL;
0405 break;
0406 case SPEED_1000:
0407 netdev_dbg(adapter->netdev,
0408 "1000 Mbps Speed specified without Duplex\n");
0409 goto full_duplex_only;
0410 case SPEED_1000 + HALF_DUPLEX:
0411 netdev_dbg(adapter->netdev,
0412 "Half Duplex is not supported at 1000 Mbps\n");
0413 fallthrough;
0414 case SPEED_1000 + FULL_DUPLEX:
0415 full_duplex_only:
0416 netdev_dbg(adapter->netdev,
0417 "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
0418 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
0419 hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
0420 hw->mac.link_speed = SPEED_1000;
0421 hw->mac.link_duplex = DUPLEX_FULL;
0422 break;
0423 default:
0424 BUG();
0425 }
0426 }
0427
0428
0429
0430
0431
0432 void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
0433 {
0434 struct pch_gbe_hw *hw = &adapter->hw;
0435 struct net_device *dev = adapter->netdev;
0436 int val;
0437
0438 {
0439 static const struct pch_gbe_option opt = {
0440 .type = range_option,
0441 .name = "Transmit Descriptors",
0442 .err = "using default of "
0443 __MODULE_STRING(PCH_GBE_DEFAULT_TXD),
0444 .def = PCH_GBE_DEFAULT_TXD,
0445 .arg = { .r = { .min = PCH_GBE_MIN_TXD,
0446 .max = PCH_GBE_MAX_TXD } }
0447 };
0448 struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
0449 tx_ring->count = TxDescriptors;
0450 pch_gbe_validate_option(&tx_ring->count, &opt, adapter);
0451 tx_ring->count = roundup(tx_ring->count,
0452 PCH_GBE_TX_DESC_MULTIPLE);
0453 }
0454 {
0455 static const struct pch_gbe_option opt = {
0456 .type = range_option,
0457 .name = "Receive Descriptors",
0458 .err = "using default of "
0459 __MODULE_STRING(PCH_GBE_DEFAULT_RXD),
0460 .def = PCH_GBE_DEFAULT_RXD,
0461 .arg = { .r = { .min = PCH_GBE_MIN_RXD,
0462 .max = PCH_GBE_MAX_RXD } }
0463 };
0464 struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
0465 rx_ring->count = RxDescriptors;
0466 pch_gbe_validate_option(&rx_ring->count, &opt, adapter);
0467 rx_ring->count = roundup(rx_ring->count,
0468 PCH_GBE_RX_DESC_MULTIPLE);
0469 }
0470 {
0471 static const struct pch_gbe_option opt = {
0472 .type = enable_option,
0473 .name = "Checksum Offload",
0474 .err = "defaulting to Enabled",
0475 .def = PCH_GBE_DEFAULT_RX_CSUM
0476 };
0477 val = XsumRX;
0478 pch_gbe_validate_option(&val, &opt, adapter);
0479 if (!val)
0480 dev->features &= ~NETIF_F_RXCSUM;
0481 }
0482 {
0483 static const struct pch_gbe_option opt = {
0484 .type = enable_option,
0485 .name = "Checksum Offload",
0486 .err = "defaulting to Enabled",
0487 .def = PCH_GBE_DEFAULT_TX_CSUM
0488 };
0489 val = XsumTX;
0490 pch_gbe_validate_option(&val, &opt, adapter);
0491 if (!val)
0492 dev->features &= ~NETIF_F_CSUM_MASK;
0493 }
0494 {
0495 static const struct pch_gbe_option opt = {
0496 .type = list_option,
0497 .name = "Flow Control",
0498 .err = "reading default settings from EEPROM",
0499 .def = PCH_GBE_FC_DEFAULT,
0500 .arg = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
0501 .p = fc_list } }
0502 };
0503 int tmp = FlowControl;
0504
0505 pch_gbe_validate_option(&tmp, &opt, adapter);
0506 hw->mac.fc = tmp;
0507 }
0508
0509 pch_gbe_check_copper_options(adapter);
0510 }