Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /******************************************************************************* |
2 | ||
0abb6eb1 | 3 | Intel PRO/10GbE Linux driver |
f731a9ef | 4 | Copyright(c) 1999 - 2008 Intel Corporation. |
0abb6eb1 AK |
5 | |
6 | This program is free software; you can redistribute it and/or modify it | |
7 | under the terms and conditions of the GNU General Public License, | |
8 | version 2, as published by the Free Software Foundation. | |
9 | ||
10 | This program is distributed in the hope it will be useful, but WITHOUT | |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
1da177e4 | 13 | more details. |
0abb6eb1 | 14 | |
1da177e4 | 15 | You should have received a copy of the GNU General Public License along with |
0abb6eb1 AK |
16 | this program; if not, write to the Free Software Foundation, Inc., |
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | ||
19 | The full GNU General Public License is included in this distribution in | |
20 | the file called "COPYING". | |
21 | ||
1da177e4 LT |
22 | Contact Information: |
23 | Linux NICS <linux.nics@intel.com> | |
0abb6eb1 | 24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> |
1da177e4 LT |
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
26 | ||
27 | *******************************************************************************/ | |
28 | ||
29 | #include "ixgb.h" | |
30 | ||
31 | /* This is the only thing that needs to be changed to adjust the | |
32 | * maximum number of ports that the driver can manage. | |
33 | */ | |
34 | ||
35 | #define IXGB_MAX_NIC 8 | |
36 | ||
37 | #define OPTION_UNSET -1 | |
38 | #define OPTION_DISABLED 0 | |
39 | #define OPTION_ENABLED 1 | |
40 | ||
41 | /* All parameters are treated the same, as an integer array of values. | |
42 | * This macro just reduces the need to repeat the same declaration code | |
43 | * over and over (plus this helps to avoid typo bugs). | |
44 | */ | |
45 | ||
46 | #define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET } | |
273dc74e SH |
47 | #define IXGB_PARAM(X, desc) \ |
48 | static int __devinitdata X[IXGB_MAX_NIC+1] \ | |
49 | = IXGB_PARAM_INIT; \ | |
50 | static unsigned int num_##X = 0; \ | |
51 | module_param_array_named(X, X, int, &num_##X, 0); \ | |
1da177e4 LT |
52 | MODULE_PARM_DESC(X, desc); |
53 | ||
54 | /* Transmit Descriptor Count | |
55 | * | |
56 | * Valid Range: 64-4096 | |
57 | * | |
58 | * Default Value: 256 | |
59 | */ | |
60 | ||
61 | IXGB_PARAM(TxDescriptors, "Number of transmit descriptors"); | |
62 | ||
63 | /* Receive Descriptor Count | |
64 | * | |
65 | * Valid Range: 64-4096 | |
66 | * | |
67 | * Default Value: 1024 | |
68 | */ | |
69 | ||
70 | IXGB_PARAM(RxDescriptors, "Number of receive descriptors"); | |
71 | ||
72 | /* User Specified Flow Control Override | |
73 | * | |
74 | * Valid Range: 0-3 | |
75 | * - 0 - No Flow Control | |
76 | * - 1 - Rx only, respond to PAUSE frames but do not generate them | |
77 | * - 2 - Tx only, generate PAUSE frames but ignore them on receive | |
78 | * - 3 - Full Flow Control Support | |
79 | * | |
953784d6 | 80 | * Default Value: 2 - Tx only (silicon bug avoidance) |
1da177e4 LT |
81 | */ |
82 | ||
83 | IXGB_PARAM(FlowControl, "Flow Control setting"); | |
84 | ||
85 | /* XsumRX - Receive Checksum Offload Enable/Disable | |
86 | * | |
87 | * Valid Range: 0, 1 | |
88 | * - 0 - disables all checksum offload | |
89 | * - 1 - enables receive IP/TCP/UDP checksum offload | |
90 | * on 82597 based NICs | |
91 | * | |
92 | * Default Value: 1 | |
93 | */ | |
94 | ||
95 | IXGB_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); | |
96 | ||
97 | /* Transmit Interrupt Delay in units of 0.8192 microseconds | |
98 | * | |
99 | * Valid Range: 0-65535 | |
100 | * | |
101 | * Default Value: 32 | |
102 | */ | |
103 | ||
104 | IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay"); | |
105 | ||
106 | /* Receive Interrupt Delay in units of 0.8192 microseconds | |
107 | * | |
108 | * Valid Range: 0-65535 | |
109 | * | |
110 | * Default Value: 72 | |
111 | */ | |
112 | ||
113 | IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay"); | |
114 | ||
115 | /* Receive Flow control high threshold (when we send a pause frame) | |
116 | * (FCRTH) | |
117 | * | |
118 | * Valid Range: 1,536 - 262,136 (0x600 - 0x3FFF8, 8 byte granularity) | |
119 | * | |
120 | * Default Value: 196,608 (0x30000) | |
121 | */ | |
122 | ||
123 | IXGB_PARAM(RxFCHighThresh, "Receive Flow Control High Threshold"); | |
124 | ||
125 | /* Receive Flow control low threshold (when we send a resume frame) | |
126 | * (FCRTL) | |
127 | * | |
128 | * Valid Range: 64 - 262,136 (0x40 - 0x3FFF8, 8 byte granularity) | |
129 | * must be less than high threshold by at least 8 bytes | |
130 | * | |
131 | * Default Value: 163,840 (0x28000) | |
132 | */ | |
133 | ||
134 | IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold"); | |
135 | ||
136 | /* Flow control request timeout (how long to pause the link partner's tx) | |
137 | * (PAP 15:0) | |
138 | * | |
0060c072 | 139 | * Valid Range: 1 - 65535 |
1da177e4 | 140 | * |
953784d6 | 141 | * Default Value: 65535 (0xffff) (we'll send an xon if we recover) |
1da177e4 LT |
142 | */ |
143 | ||
144 | IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout"); | |
145 | ||
146 | /* Interrupt Delay Enable | |
147 | * | |
148 | * Valid Range: 0, 1 | |
149 | * | |
150 | * - 0 - disables transmit interrupt delay | |
151 | * - 1 - enables transmmit interrupt delay | |
152 | * | |
153 | * Default Value: 1 | |
154 | */ | |
155 | ||
156 | IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable"); | |
157 | ||
158 | ||
159 | #define DEFAULT_TIDV 32 | |
160 | #define MAX_TIDV 0xFFFF | |
161 | #define MIN_TIDV 0 | |
162 | ||
163 | #define DEFAULT_RDTR 72 | |
164 | #define MAX_RDTR 0xFFFF | |
165 | #define MIN_RDTR 0 | |
166 | ||
167 | #define XSUMRX_DEFAULT OPTION_ENABLED | |
168 | ||
1da177e4 LT |
169 | #define DEFAULT_FCRTL 0x28000 |
170 | #define DEFAULT_FCRTH 0x30000 | |
171 | #define MIN_FCRTL 0 | |
172 | #define MAX_FCRTL 0x3FFE8 | |
173 | #define MIN_FCRTH 8 | |
174 | #define MAX_FCRTH 0x3FFF0 | |
175 | ||
1da177e4 LT |
176 | #define MIN_FCPAUSE 1 |
177 | #define MAX_FCPAUSE 0xffff | |
953784d6 | 178 | #define DEFAULT_FCPAUSE 0xFFFF /* this may be too long */ |
1da177e4 LT |
179 | |
180 | struct ixgb_option { | |
181 | enum { enable_option, range_option, list_option } type; | |
273dc74e SH |
182 | const char *name; |
183 | const char *err; | |
1da177e4 LT |
184 | int def; |
185 | union { | |
186 | struct { /* range_option info */ | |
187 | int min; | |
188 | int max; | |
189 | } r; | |
190 | struct { /* list_option info */ | |
191 | int nr; | |
192 | struct ixgb_opt_list { | |
193 | int i; | |
194 | char *str; | |
195 | } *p; | |
196 | } l; | |
197 | } arg; | |
198 | }; | |
199 | ||
200 | static int __devinit | |
273dc74e | 201 | ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt) |
1da177e4 | 202 | { |
03f83041 | 203 | if (*value == OPTION_UNSET) { |
1da177e4 LT |
204 | *value = opt->def; |
205 | return 0; | |
206 | } | |
207 | ||
208 | switch (opt->type) { | |
209 | case enable_option: | |
210 | switch (*value) { | |
211 | case OPTION_ENABLED: | |
212 | printk(KERN_INFO "%s Enabled\n", opt->name); | |
213 | return 0; | |
214 | case OPTION_DISABLED: | |
215 | printk(KERN_INFO "%s Disabled\n", opt->name); | |
216 | return 0; | |
217 | } | |
218 | break; | |
219 | case range_option: | |
03f83041 | 220 | if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { |
1da177e4 LT |
221 | printk(KERN_INFO "%s set to %i\n", opt->name, *value); |
222 | return 0; | |
223 | } | |
224 | break; | |
225 | case list_option: { | |
226 | int i; | |
227 | struct ixgb_opt_list *ent; | |
228 | ||
1459336d | 229 | for (i = 0; i < opt->arg.l.nr; i++) { |
1da177e4 | 230 | ent = &opt->arg.l.p[i]; |
03f83041 JB |
231 | if (*value == ent->i) { |
232 | if (ent->str[0] != '\0') | |
1da177e4 LT |
233 | printk(KERN_INFO "%s\n", ent->str); |
234 | return 0; | |
235 | } | |
236 | } | |
237 | } | |
238 | break; | |
239 | default: | |
240 | BUG(); | |
241 | } | |
242 | ||
243 | printk(KERN_INFO "Invalid %s specified (%i) %s\n", | |
244 | opt->name, *value, opt->err); | |
245 | *value = opt->def; | |
246 | return -1; | |
247 | } | |
248 | ||
1da177e4 LT |
249 | /** |
250 | * ixgb_check_options - Range Checking for Command Line Parameters | |
251 | * @adapter: board private structure | |
252 | * | |
253 | * This routine checks all command line parameters for valid user | |
254 | * input. If an invalid value is given, or if no user specified | |
255 | * value exists, a default value is used. The final value is stored | |
256 | * in a variable in the adapter structure. | |
257 | **/ | |
258 | ||
259 | void __devinit | |
260 | ixgb_check_options(struct ixgb_adapter *adapter) | |
261 | { | |
262 | int bd = adapter->bd_number; | |
03f83041 | 263 | if (bd >= IXGB_MAX_NIC) { |
1da177e4 LT |
264 | printk(KERN_NOTICE |
265 | "Warning: no configuration for board #%i\n", bd); | |
266 | printk(KERN_NOTICE "Using defaults for all values\n"); | |
267 | } | |
268 | ||
269 | { /* Transmit Descriptor Count */ | |
273dc74e | 270 | const struct ixgb_option opt = { |
1da177e4 LT |
271 | .type = range_option, |
272 | .name = "Transmit Descriptors", | |
273 | .err = "using default of " __MODULE_STRING(DEFAULT_TXD), | |
274 | .def = DEFAULT_TXD, | |
275 | .arg = { .r = { .min = MIN_TXD, | |
276 | .max = MAX_TXD}} | |
277 | }; | |
278 | struct ixgb_desc_ring *tx_ring = &adapter->tx_ring; | |
279 | ||
03f83041 | 280 | if (num_TxDescriptors > bd) { |
1da177e4 LT |
281 | tx_ring->count = TxDescriptors[bd]; |
282 | ixgb_validate_option(&tx_ring->count, &opt); | |
283 | } else { | |
284 | tx_ring->count = opt.def; | |
285 | } | |
55e924cf | 286 | tx_ring->count = ALIGN(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE); |
1da177e4 LT |
287 | } |
288 | { /* Receive Descriptor Count */ | |
273dc74e | 289 | const struct ixgb_option opt = { |
1da177e4 LT |
290 | .type = range_option, |
291 | .name = "Receive Descriptors", | |
292 | .err = "using default of " __MODULE_STRING(DEFAULT_RXD), | |
293 | .def = DEFAULT_RXD, | |
294 | .arg = { .r = { .min = MIN_RXD, | |
295 | .max = MAX_RXD}} | |
296 | }; | |
297 | struct ixgb_desc_ring *rx_ring = &adapter->rx_ring; | |
298 | ||
03f83041 | 299 | if (num_RxDescriptors > bd) { |
1da177e4 LT |
300 | rx_ring->count = RxDescriptors[bd]; |
301 | ixgb_validate_option(&rx_ring->count, &opt); | |
302 | } else { | |
303 | rx_ring->count = opt.def; | |
304 | } | |
55e924cf | 305 | rx_ring->count = ALIGN(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE); |
1da177e4 LT |
306 | } |
307 | { /* Receive Checksum Offload Enable */ | |
273dc74e | 308 | const struct ixgb_option opt = { |
1da177e4 LT |
309 | .type = enable_option, |
310 | .name = "Receive Checksum Offload", | |
311 | .err = "defaulting to Enabled", | |
312 | .def = OPTION_ENABLED | |
313 | }; | |
314 | ||
03f83041 | 315 | if (num_XsumRX > bd) { |
273dc74e | 316 | unsigned int rx_csum = XsumRX[bd]; |
1da177e4 LT |
317 | ixgb_validate_option(&rx_csum, &opt); |
318 | adapter->rx_csum = rx_csum; | |
319 | } else { | |
320 | adapter->rx_csum = opt.def; | |
321 | } | |
322 | } | |
323 | { /* Flow Control */ | |
324 | ||
325 | struct ixgb_opt_list fc_list[] = | |
326 | {{ ixgb_fc_none, "Flow Control Disabled" }, | |
327 | { ixgb_fc_rx_pause,"Flow Control Receive Only" }, | |
328 | { ixgb_fc_tx_pause,"Flow Control Transmit Only" }, | |
329 | { ixgb_fc_full, "Flow Control Enabled" }, | |
330 | { ixgb_fc_default, "Flow Control Hardware Default" }}; | |
331 | ||
273dc74e | 332 | const struct ixgb_option opt = { |
1da177e4 LT |
333 | .type = list_option, |
334 | .name = "Flow Control", | |
335 | .err = "reading default settings from EEPROM", | |
953784d6 | 336 | .def = ixgb_fc_tx_pause, |
1c8816c6 | 337 | .arg = { .l = { .nr = ARRAY_SIZE(fc_list), |
1da177e4 LT |
338 | .p = fc_list }} |
339 | }; | |
340 | ||
03f83041 | 341 | if (num_FlowControl > bd) { |
273dc74e | 342 | unsigned int fc = FlowControl[bd]; |
1da177e4 LT |
343 | ixgb_validate_option(&fc, &opt); |
344 | adapter->hw.fc.type = fc; | |
345 | } else { | |
346 | adapter->hw.fc.type = opt.def; | |
347 | } | |
348 | } | |
349 | { /* Receive Flow Control High Threshold */ | |
273dc74e | 350 | const struct ixgb_option opt = { |
1da177e4 LT |
351 | .type = range_option, |
352 | .name = "Rx Flow Control High Threshold", | |
353 | .err = "using default of " __MODULE_STRING(DEFAULT_FCRTH), | |
354 | .def = DEFAULT_FCRTH, | |
355 | .arg = { .r = { .min = MIN_FCRTH, | |
356 | .max = MAX_FCRTH}} | |
357 | }; | |
358 | ||
03f83041 | 359 | if (num_RxFCHighThresh > bd) { |
1da177e4 LT |
360 | adapter->hw.fc.high_water = RxFCHighThresh[bd]; |
361 | ixgb_validate_option(&adapter->hw.fc.high_water, &opt); | |
362 | } else { | |
363 | adapter->hw.fc.high_water = opt.def; | |
364 | } | |
953784d6 | 365 | if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) ) |
8441dab2 | 366 | printk(KERN_INFO |
1da177e4 LT |
367 | "Ignoring RxFCHighThresh when no RxFC\n"); |
368 | } | |
369 | { /* Receive Flow Control Low Threshold */ | |
273dc74e | 370 | const struct ixgb_option opt = { |
1da177e4 LT |
371 | .type = range_option, |
372 | .name = "Rx Flow Control Low Threshold", | |
373 | .err = "using default of " __MODULE_STRING(DEFAULT_FCRTL), | |
374 | .def = DEFAULT_FCRTL, | |
375 | .arg = { .r = { .min = MIN_FCRTL, | |
376 | .max = MAX_FCRTL}} | |
377 | }; | |
378 | ||
03f83041 | 379 | if (num_RxFCLowThresh > bd) { |
1da177e4 LT |
380 | adapter->hw.fc.low_water = RxFCLowThresh[bd]; |
381 | ixgb_validate_option(&adapter->hw.fc.low_water, &opt); | |
382 | } else { | |
383 | adapter->hw.fc.low_water = opt.def; | |
384 | } | |
953784d6 | 385 | if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) ) |
8441dab2 | 386 | printk(KERN_INFO |
1da177e4 LT |
387 | "Ignoring RxFCLowThresh when no RxFC\n"); |
388 | } | |
389 | { /* Flow Control Pause Time Request*/ | |
273dc74e | 390 | const struct ixgb_option opt = { |
1da177e4 LT |
391 | .type = range_option, |
392 | .name = "Flow Control Pause Time Request", | |
393 | .err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE), | |
394 | .def = DEFAULT_FCPAUSE, | |
395 | .arg = { .r = { .min = MIN_FCPAUSE, | |
396 | .max = MAX_FCPAUSE}} | |
397 | }; | |
398 | ||
03f83041 | 399 | if (num_FCReqTimeout > bd) { |
273dc74e | 400 | unsigned int pause_time = FCReqTimeout[bd]; |
1da177e4 LT |
401 | ixgb_validate_option(&pause_time, &opt); |
402 | adapter->hw.fc.pause_time = pause_time; | |
403 | } else { | |
404 | adapter->hw.fc.pause_time = opt.def; | |
405 | } | |
953784d6 | 406 | if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) ) |
8441dab2 | 407 | printk(KERN_INFO |
1da177e4 LT |
408 | "Ignoring FCReqTimeout when no RxFC\n"); |
409 | } | |
410 | /* high low and spacing check for rx flow control thresholds */ | |
953784d6 | 411 | if (adapter->hw.fc.type & ixgb_fc_tx_pause) { |
1da177e4 LT |
412 | /* high must be greater than low */ |
413 | if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) { | |
414 | /* set defaults */ | |
8441dab2 | 415 | printk(KERN_INFO |
1da177e4 LT |
416 | "RxFCHighThresh must be >= (RxFCLowThresh + 8), " |
417 | "Using Defaults\n"); | |
418 | adapter->hw.fc.high_water = DEFAULT_FCRTH; | |
419 | adapter->hw.fc.low_water = DEFAULT_FCRTL; | |
420 | } | |
421 | } | |
422 | { /* Receive Interrupt Delay */ | |
273dc74e | 423 | const struct ixgb_option opt = { |
1da177e4 LT |
424 | .type = range_option, |
425 | .name = "Receive Interrupt Delay", | |
426 | .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), | |
427 | .def = DEFAULT_RDTR, | |
428 | .arg = { .r = { .min = MIN_RDTR, | |
429 | .max = MAX_RDTR}} | |
430 | }; | |
431 | ||
03f83041 | 432 | if (num_RxIntDelay > bd) { |
1da177e4 LT |
433 | adapter->rx_int_delay = RxIntDelay[bd]; |
434 | ixgb_validate_option(&adapter->rx_int_delay, &opt); | |
435 | } else { | |
436 | adapter->rx_int_delay = opt.def; | |
437 | } | |
438 | } | |
439 | { /* Transmit Interrupt Delay */ | |
273dc74e | 440 | const struct ixgb_option opt = { |
1da177e4 LT |
441 | .type = range_option, |
442 | .name = "Transmit Interrupt Delay", | |
443 | .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), | |
444 | .def = DEFAULT_TIDV, | |
445 | .arg = { .r = { .min = MIN_TIDV, | |
446 | .max = MAX_TIDV}} | |
447 | }; | |
448 | ||
03f83041 | 449 | if (num_TxIntDelay > bd) { |
1da177e4 LT |
450 | adapter->tx_int_delay = TxIntDelay[bd]; |
451 | ixgb_validate_option(&adapter->tx_int_delay, &opt); | |
452 | } else { | |
453 | adapter->tx_int_delay = opt.def; | |
454 | } | |
455 | } | |
456 | ||
457 | { /* Transmit Interrupt Delay Enable */ | |
273dc74e | 458 | const struct ixgb_option opt = { |
1da177e4 LT |
459 | .type = enable_option, |
460 | .name = "Tx Interrupt Delay Enable", | |
461 | .err = "defaulting to Enabled", | |
462 | .def = OPTION_ENABLED | |
463 | }; | |
464 | ||
03f83041 | 465 | if (num_IntDelayEnable > bd) { |
273dc74e | 466 | unsigned int ide = IntDelayEnable[bd]; |
1da177e4 LT |
467 | ixgb_validate_option(&ide, &opt); |
468 | adapter->tx_int_delay_enable = ide; | |
469 | } else { | |
470 | adapter->tx_int_delay_enable = opt.def; | |
471 | } | |
472 | } | |
473 | } |