1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 1999 - 2010 Intel Corporation.
4 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
6 * This code was derived from the Intel e1000e Linux driver.
10 #include <linux/module.h> /* for __MODULE_STRING */
12 #define OPTION_UNSET -1
13 #define OPTION_DISABLED 0
14 #define OPTION_ENABLED 1
17 * TxDescriptors - Transmit Descriptor Count
18 * @Valid Range: PCH_GBE_MIN_TXD - PCH_GBE_MAX_TXD
19 * @Default Value: PCH_GBE_DEFAULT_TXD
21 static int TxDescriptors = OPTION_UNSET;
22 module_param(TxDescriptors, int, 0);
23 MODULE_PARM_DESC(TxDescriptors, "Number of transmit descriptors");
26 * RxDescriptors -Receive Descriptor Count
27 * @Valid Range: PCH_GBE_MIN_RXD - PCH_GBE_MAX_RXD
28 * @Default Value: PCH_GBE_DEFAULT_RXD
30 static int RxDescriptors = OPTION_UNSET;
31 module_param(RxDescriptors, int, 0);
32 MODULE_PARM_DESC(RxDescriptors, "Number of receive descriptors");
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
43 static int Speed = OPTION_UNSET;
44 module_param(Speed, int, 0);
45 MODULE_PARM_DESC(Speed, "Speed setting");
48 * Duplex - User Specified Duplex Override
50 * - 0: auto-negotiate for duplex
51 * - 1: only link at half duplex
52 * - 2: only link at full duplex
55 static int Duplex = OPTION_UNSET;
56 module_param(Duplex, int, 0);
57 MODULE_PARM_DESC(Duplex, "Duplex setting");
63 * AutoNeg - Auto-negotiation Advertisement Override
64 * @Valid Range: 0x01-0x0F, 0x20-0x2F
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
71 * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
72 * Duplex Full Full Half Full Half
74 * @Default Value: 0x2F (copper)
76 static int AutoNeg = OPTION_UNSET;
77 module_param(AutoNeg, int, 0);
78 MODULE_PARM_DESC(AutoNeg, "Advertised auto-negotiation setting");
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
89 * FlowControl - User Specified Flow Control Override
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
97 static int FlowControl = OPTION_UNSET;
98 module_param(FlowControl, int, 0);
99 MODULE_PARM_DESC(FlowControl, "Flow Control setting");
102 * XsumRX - Receive Checksum Offload Enable/Disable
104 * - 0: disables all checksum offload
105 * - 1: enables receive IP/TCP/UDP checksum offload
106 * @Default Value: PCH_GBE_DEFAULT_RX_CSUM
108 static int XsumRX = OPTION_UNSET;
109 module_param(XsumRX, int, 0);
110 MODULE_PARM_DESC(XsumRX, "Disable or enable Receive Checksum offload");
112 #define PCH_GBE_DEFAULT_RX_CSUM true /* trueorfalse */
115 * XsumTX - Transmit Checksum Offload Enable/Disable
117 * - 0: disables all checksum offload
118 * - 1: enables transmit IP/TCP/UDP checksum offload
119 * @Default Value: PCH_GBE_DEFAULT_TX_CSUM
121 static int XsumTX = OPTION_UNSET;
122 module_param(XsumTX, int, 0);
123 MODULE_PARM_DESC(XsumTX, "Disable or enable Transmit Checksum offload");
125 #define PCH_GBE_DEFAULT_TX_CSUM true /* trueorfalse */
128 * pch_gbe_option - Force the MAC's flow control settings
129 * @hw: Pointer to the HW structure
132 * Negative value: Failed.
134 struct pch_gbe_option {
135 enum { enable_option, range_option, list_option } type;
140 struct { /* range_option info */
144 struct { /* list_option info */
146 const struct pch_gbe_opt_list { int i; char *str; } *p;
151 static const struct pch_gbe_opt_list speed_list[] = {
158 static const struct pch_gbe_opt_list dplx_list[] = {
164 static 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" }
199 static 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" }
207 * pch_gbe_validate_option - Validate option
210 * @adapter: Board private structure
213 * Negative value: Failed.
215 static int pch_gbe_validate_option(int *value,
216 const struct pch_gbe_option *opt,
217 struct pch_gbe_adapter *adapter)
219 if (*value == OPTION_UNSET) {
228 netdev_dbg(adapter->netdev, "%s Enabled\n", opt->name);
230 case OPTION_DISABLED:
231 netdev_dbg(adapter->netdev, "%s Disabled\n", opt->name);
236 if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
237 netdev_dbg(adapter->netdev, "%s set to %i\n",
244 const struct pch_gbe_opt_list *ent;
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",
261 netdev_dbg(adapter->netdev, "Invalid %s value specified (%i) %s\n",
262 opt->name, *value, opt->err);
268 * pch_gbe_check_copper_options - Range Checking for Link Options, Copper Version
269 * @adapter: Board private structure
271 static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
273 struct pch_gbe_hw *hw = &adapter->hw;
277 static const struct pch_gbe_option opt = {
280 .err = "parameter ignored",
282 .arg = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
286 pch_gbe_validate_option(&speed, &opt, adapter);
289 static const struct pch_gbe_option opt = {
292 .err = "parameter ignored",
294 .arg = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
298 pch_gbe_validate_option(&dplx, &opt, adapter);
302 static const struct pch_gbe_option opt = {
305 .err = "parameter ignored",
306 .def = PCH_AUTONEG_ADVERTISE_DEFAULT,
307 .arg = { .l = { .nr = (int)ARRAY_SIZE(an_list),
311 netdev_dbg(adapter->netdev,
312 "AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
313 hw->phy.autoneg_advertised = opt.def;
317 pch_gbe_validate_option(&tmp, &opt, adapter);
318 hw->phy.autoneg_advertised = tmp;
322 switch (speed + dplx) {
324 hw->mac.autoneg = hw->mac.fc_autoneg = 1;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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");
414 case SPEED_1000 + FULL_DUPLEX:
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;
429 * pch_gbe_check_options - Range Checking for Command Line Parameters
430 * @adapter: Board private structure
432 void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
434 struct pch_gbe_hw *hw = &adapter->hw;
435 struct net_device *dev = adapter->netdev;
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 } }
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);
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 } }
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);
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
478 pch_gbe_validate_option(&val, &opt, adapter);
480 dev->features &= ~NETIF_F_RXCSUM;
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
490 pch_gbe_validate_option(&val, &opt, adapter);
492 dev->features &= ~NETIF_F_CSUM_MASK;
495 static const struct pch_gbe_option opt = {
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),
503 int tmp = FlowControl;
505 pch_gbe_validate_option(&tmp, &opt, adapter);
509 pch_gbe_check_copper_options(adapter);