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
);