aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/networking/ip-sysctl.txt
blob: 8f6067ea5e3e7eb26a2f8771f7d727ad5d0eb23d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
/proc/sys/net/ipv4/* Variables:

ip_forward - BOOLEAN
	0 - disabled (default)
	not 0 - enabled 

	Forward Packets between interfaces.

	This variable is special, its change resets all configuration
	parameters to their default state (RFC1122 for hosts, RFC1812
	for routers)

ip_default_ttl - INTEGER
	default 64

ip_no_pmtu_disc - BOOLEAN
	Disable Path MTU Discovery.
	default FALSE

min_pmtu - INTEGER
	default 562 - minimum discovered Path MTU

mtu_expires - INTEGER
	Time, in seconds, that cached PMTU information is kept.

min_adv_mss - INTEGER
	The advertised MSS depends on the first hop route MTU, but will
	never be lower than this setting.

IP Fragmentation:

ipfrag_high_thresh - INTEGER
	Maximum memory used to reassemble IP fragments. When 
	ipfrag_high_thresh bytes of memory is allocated for this purpose,
	the fragment handler will toss packets until ipfrag_low_thresh
	is reached.
	
ipfrag_low_thresh - INTEGER
	See ipfrag_high_thresh	

ipfrag_time - INTEGER
	Time in seconds to keep an IP fragment in memory.	

ipfrag_secret_interval - INTEGER
	Regeneration interval (in seconds) of the hash secret (or lifetime 
	for the hash secret) for IP fragments.
	Default: 600

ipfrag_max_dist - INTEGER
	ipfrag_max_dist is a non-negative integer value which defines the 
	maximum "disorder" which is allowed among fragments which share a 
	common IP source address. Note that reordering of packets is 
	not unusual, but if a large number of fragments arrive from a source 
	IP address while a particular fragment queue remains incomplete, it 
	probably indicates that one or more fragments belonging to that queue 
	have been lost. When ipfrag_max_dist is positive, an additional check 
	is done on fragments before they are added to a reassembly queue - if 
	ipfrag_max_dist (or more) fragments have arrived from a particular IP 
	address between additions to any IP fragment queue using that source 
	address, it's presumed that one or more fragments in the queue are 
	lost. The existing fragment queue will be dropped, and a new one 
	started. An ipfrag_max_dist value of zero disables this check.

	Using a very small value, e.g. 1 or 2, for ipfrag_max_dist can
	result in unnecessarily dropping fragment queues when normal
	reordering of packets occurs, which could lead to poor application 
	performance. Using a very large value, e.g. 50000, increases the 
	likelihood of incorrectly reassembling IP fragments that originate 
	from different IP datagrams, which could result in data corruption.
	Default: 64

INET peer storage:

inet_peer_threshold - INTEGER
	The approximate size of the storage.  Starting from this threshold	
	entries will be thrown aggressively.  This threshold also determines
	entries' time-to-live and time intervals between garbage collection
	passes.  More entries, less time-to-live, less GC interval.

inet_peer_minttl - INTEGER
	Minimum time-to-live of entries.  Should be enough to cover fragment
	time-to-live on the reassembling side.  This minimum time-to-live  is
	guaranteed if the pool size is less than inet_peer_threshold.
	Measured in jiffies(1).

inet_peer_maxttl - INTEGER
	Maximum time-to-live of entries.  Unused entries will expire after
	this period of time if there is no memory pressure on the pool (i.e.
	when the number of entries in the pool is very small).
	Measured in jiffies(1).

inet_peer_gc_mintime - INTEGER
	Minimum interval between garbage collection passes.  This interval is
	in effect under high memory pressure on the pool.
	Measured in jiffies(1).

inet_peer_gc_maxtime - INTEGER
	Minimum interval between garbage collection passes.  This interval is
	in effect under low (or absent) memory pressure on the pool.
	Measured in jiffies(1).

TCP variables: 

somaxconn - INTEGER
	Limit of socket listen() backlog, known in userspace as SOMAXCONN.
	Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
	for TCP sockets.

tcp_abc - INTEGER
	Controls Appropriate Byte Count (ABC) defined in RFC3465.
	ABC is a way of increasing congestion window (cwnd) more slowly
	in response to partial acknowledgments.
	Possible values are:
		0 increase cwnd once per acknowledgment (no ABC)
		1 increase cwnd once per acknowledgment of full sized segment
		2 allow increase cwnd by two if acknowledgment is
		  of two segments to compensate for delayed acknowledgments.
	Default: 0 (off)

tcp_abort_on_overflow - BOOLEAN
	If listening service is too slow to accept new connections,
	reset them. Default state is FALSE. It means that if overflow
	occurred due to a burst, connection will recover. Enable this
	option _only_ if you are really sure that listening daemon
	cannot be tuned to accept connections faster. Enabling this
	option can harm clients of your server.

tcp_adv_win_scale - INTEGER
	Count buffering overhead as bytes/2^tcp_adv_win_scale
	(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
	if it is <= 0.
	Default: 2

tcp_allowed_congestion_control - STRING
	Show/set the congestion control choices available to non-privileged
	processes. The list is a subset of those listed in
	tcp_available_congestion_control.
	Default is "reno" and the default setting (tcp_congestion_control).

tcp_app_win - INTEGER
	Reserve max(window/2^tcp_app_win, mss) of window for application
	buffer. Value 0 is special, it means that nothing is reserved.
	Default: 31

tcp_available_congestion_control - STRING
	Shows the available congestion control choices that are registered.
	More congestion control algorithms may be available as modules,
	but not loaded.

tcp_base_mss - INTEGER
	The initial value of search_low to be used by Packetization Layer
	Path MTU Discovery (MTU probing).  If MTU probing is enabled,
	this is the inital MSS used by the connection.

tcp_congestion_control - STRING
	Set the congestion control algorithm to be used for new
	connections. The algorithm "reno" is always available, but
	additional choices may be available based on kernel configuration.
	Default is set as part of kernel configuration.

tcp_dsack - BOOLEAN
	Allows TCP to send "duplicate" SACKs.

tcp_ecn - BOOLEAN
	Enable Explicit Congestion Notification in TCP.

tcp_fack - BOOLEAN
	Enable FACK congestion avoidance and fast retransmission.
	The value is not used, if tcp_sack is not enabled.

tcp_fin_timeout - INTEGER
	Time to hold socket in state FIN-WAIT-2, if it was closed
	by our side. Peer can be broken and never close its side,
	or even died unexpectedly. Default value is 60sec.
	Usual value used in 2.2 was 180 seconds, you may restore
	it, but remember that if your machine is even underloaded WEB server,
	you risk to overflow memory with kilotons of dead sockets,
	FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
	because they eat maximum 1.5K of memory, but they tend
	to live longer.	Cf. tcp_max_orphans.

tcp_frto - INTEGER
	Enables F-RTO, an enhanced recovery algorithm for TCP retransmission
	timeouts.  It is particularly beneficial in wireless environments
	where packet loss is typically due to random radio interference
	rather than intermediate router congestion. If set to 1, basic
	version is enabled. 2 enables SACK enhanced F-RTO, which is
	EXPERIMENTAL. The basic version can be used also when SACK is
	enabled for a flow through tcp_sack sysctl.

tcp_frto_response - INTEGER
	When F-RTO has detected that a TCP retransmission timeout was
	spurious (i.e, the timeout would have been avoided had TCP set a
	longer retransmission timeout), TCP has several options what to do
	next. Possible values are:
		0 Rate halving based; a smooth and conservative response,
		  results in halved cwnd and ssthresh after one RTT
		1 Very conservative response; not recommended because even
		  though being valid, it interacts poorly with the rest of
		  Linux TCP, halves cwnd and ssthresh immediately
		2 Aggressive response; undoes congestion control measures
		  that are now known to be unnecessary (ignoring the
		  possibility of a lost retransmission that would require
		  TCP to be more cautious), cwnd and ssthresh are restored
		  to the values prior timeout
	Default: 0 (rate halving based)

tcp_keepalive_time - INTEGER
	How often TCP sends out keepalive messages when keepalive is enabled.
	Default: 2hours.

tcp_keepalive_probes - INTEGER
	How many keepalive probes TCP sends out, until it decides that the
	connection is broken. Default value: 9.

tcp_keepalive_intvl - INTEGER
	How frequently the probes are send out. Multiplied by
	tcp_keepalive_probes it is time to kill not responding connection,
	after probes started. Default value: 75sec i.e. connection
	will be aborted after ~11 minutes of retries.

tcp_low_latency - BOOLEAN
	If set, the TCP stack makes decisions that prefer lower
	latency as opposed to higher throughput.  By default, this
	option is not set meaning that higher throughput is preferred.
	An example of an application where this default should be
	changed would be a Beowulf compute cluster.
	Default: 0

tcp_max_orphans - INTEGER
	Maximal number of TCP sockets not attached to any user file handle,
	held by system.	If this number is exceeded orphaned connections are
	reset immediately and warning is printed. This limit exists
	only to prevent simple DoS attacks, you _must_ not rely on this
	or lower the limit artificially, but rather increase it
	(probably, after increasing installed memory),
	if network conditions require more than default value,
	and tune network services to linger and kill such states
	more aggressively. Let me to remind again: each orphan eats
	up to ~64K of unswappable memory.

tcp_max_syn_backlog - INTEGER
	Maximal number of remembered connection requests, which are
	still did not receive an acknowledgment from connecting client.
	Default value is 1024 for systems with more than 128Mb of memory,
	and 128 for low memory machines. If server suffers of overload,
	try to increase this number.

tcp_max_tw_buckets - INTEGER
	Maximal number of timewait sockets held by system simultaneously.
	If this number is exceeded time-wait socket is immediately destroyed
	and warning is printed. This limit exists only to prevent
	simple DoS attacks, you _must_ not lower the limit artificially,
	but rather increase it (probably, after increasing installed memory),
	if network conditions require more than default value.

tcp_mem - vector of 3 INTEGERs: min, pressure, max
	min: below this number of pages TCP is not bothered about its
	memory appetite.

	pressure: when amount of memory allocated by TCP exceeds this number
	of pages, TCP moderates its memory consumption and enters memory
	pressure mode, which is exited when memory consumption falls
	under "min".

	max: number of pages allowed for queueing by all TCP sockets.

	Defaults are calculated at boot time from amount of available
	memory.

tcp_moderate_rcvbuf - BOOLEAN
	If set, TCP performs receive buffer autotuning, attempting to
	automatically size the buffer (no greater than tcp_rmem[2]) to
	match the size required by the path for full throughput.  Enabled by
	default.

tcp_mtu_probing - INTEGER
	Controls TCP Packetization-Layer Path MTU Discovery.  Takes three
	values:
	  0 - Disabled
	  1 - Disabled by default, enabled when an ICMP black hole detected
	  2 - Always enabled, use initial MSS of tcp_base_mss.

tcp_no_metrics_save - BOOLEAN
	By default, TCP saves various connection metrics in the route cache
	when the connection closes, so that connections established in the
	near future can use these to set initial conditions.  Usually, this
	increases overall performance, but may sometimes cause performance
	degredation.  If set, TCP will not cache metrics on closing
	connections.

tcp_orphan_retries - INTEGER
	How may times to retry before killing TCP connection, closed
	by our side. Default value 7 corresponds to ~50sec-16min
	depending on RTO. If you machine is loaded WEB server,
	you should think about lowering this value, such sockets
	may consume significant resources. Cf. tcp_max_orphans.

tcp_reordering - INTEGER
	Maximal reordering of packets in a TCP stream.
	Default: 3	

tcp_retrans_collapse - BOOLEAN
	Bug-to-bug compatibility with some broken printers.
	On retransmit try to send bigger packets to work around bugs in
	certain TCP stacks.

tcp_retries1 - INTEGER
	How many times to retry before deciding that something is wrong
	and it is necessary to report this suspicion to network layer.
	Minimal RFC value is 3, it is default, which corresponds
	to ~3sec-8min depending on RTO.

tcp_retries2 - INTEGER
	How may times to retry before killing alive TCP connection.
	RFC1122 says that the limit should be longer than 100 sec.
	It is too small number.	Default value 15 corresponds to ~13-30min
	depending on RTO.

tcp_rfc1337 - BOOLEAN
	If set, the TCP stack behaves conforming to RFC1337. If unset,
	we are not conforming to RFC, but prevent TCP TIME_WAIT
	assassination.
	Default: 0

tcp_rmem - vector of 3 INTEGERs: min, default, max
	min: Minimal size of receive buffer used by TCP sockets.
	It is guaranteed to each TCP socket, even under moderate memory
	pressure.
	Default: 8K

	default: default size of receive buffer used by TCP sockets.
	This value overrides net.core.rmem_default used by other protocols.
	Default: 87380 bytes. This value results in window of 65535 with
	default setting of tcp_adv_win_scale and tcp_app_win:0 and a bit
	less for default tcp_app_win. See below about these variables.

	max: maximal size of receive buffer allowed for automatically
	selected receiver buffers for TCP socket. This value does not override
	net.core.rmem_max, "static" selection via SO_RCVBUF does not use this.
	Default: 87380*2 bytes.

tcp_sack - BOOLEAN
	Enable select acknowledgments (SACKS).

tcp_slow_start_after_idle - BOOLEAN
	If set, provide RFC2861 behavior and time out the congestion
	window after an idle period.  An idle period is defined at
	the current RTO.  If unset, the congestion window will not
	be timed out after an idle period.
	Default: 1

tcp_stdurg - BOOLEAN
	Use the Host requirements interpretation of the TCP urg pointer field.
	Most hosts use the older BSD interpretation, so if you turn this on
	Linux might not communicate correctly with them.
	Default: FALSE

tcp_synack_retries - INTEGER
	Number of times SYNACKs for a passive TCP connection attempt will
	be retransmitted. Should not be higher than 255. Default value
	is 5, which corresponds to ~180seconds.

tcp_syncookies - BOOLEAN
	Only valid when the kernel was compiled with CONFIG_SYNCOOKIES
	Send out syncookies when the syn backlog queue of a socket
	overflows. This is to prevent against the common 'syn flood attack'
	Default: FALSE

	Note, that syncookies is fallback facility.
	It MUST NOT be used to help highly loaded servers to stand
	against legal connection rate. If you see synflood warnings
	in your logs, but investigation	shows that they occur
	because of overload with legal connections, you should tune
	another parameters until this warning disappear.
	See: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.

	syncookies seriously violate TCP protocol, do not allow
	to use TCP extensions, can result in serious degradation
	of some services (f.e. SMTP relaying), visible not by you,
	but your clients and relays, contacting you. While you see
	synflood warnings in logs not being really flooded, your server
	is seriously misconfigured.

tcp_syn_retries - INTEGER
	Number of times initial SYNs for an active TCP connection attempt
	will be retransmitted. Should not be higher than 255. Default value
	is 5, which corresponds to ~180seconds.

tcp_timestamps - BOOLEAN
	Enable timestamps as defined in RFC1323.

tcp_tso_win_divisor - INTEGER
	This allows control over what percentage of the congestion window
	can be consumed by a single TSO frame.
	The setting of this parameter is a choice between burstiness and
	building larger TSO frames.
	Default: 3

tcp_tw_recycle - BOOLEAN
	Enable fast recycling TIME-WAIT sockets. Default value is 0.
	It should not be changed without advice/request of technical
	experts.

tcp_tw_reuse - BOOLEAN
	Allow to reuse TIME-WAIT sockets for new connections when it is
	safe from protocol viewpoint. Default value is 0.
	It should not be changed without advice/request of technical
	experts.

tcp_window_scaling - BOOLEAN
	Enable window scaling as defined in RFC1323.

tcp_wmem - vector of 3 INTEGERs: min, default, max
	min: Amount of memory reserved for send buffers for TCP socket.
	Each TCP socket has rights to use it due to fact of its birth.
	Default: 4K

	default: Amount of memory allowed for send buffers for TCP socket
	by default. This value overrides net.core.wmem_default used
	by other protocols, it is usually lower than net.core.wmem_default.
	Default: 16K

	max: Maximal amount of memory allowed for automatically selected
	send buffers for TCP socket. This value does not override
	net.core.wmem_max, "static" selection via SO_SNDBUF does not use this.
	Default: 128K

tcp_workaround_signed_windows - BOOLEAN
	If set, assume no receipt of a window scaling option means the
	remote TCP is broken and treats the window as a signed quantity.
	If unset, assume the remote TCP is not broken even if we do
	not receive a window scaling option from them.
	Default: 0

tcp_dma_copybreak - INTEGER
	Lower limit, in bytes, of the size of socket reads that will be
	offloaded to a DMA copy engine, if one is present in the system
	and CONFIG_NET_DMA is enabled.
	Default: 4096

CIPSOv4 Variables:

cipso_cache_enable - BOOLEAN
	If set, enable additions to and lookups from the CIPSO label mapping
	cache.  If unset, additions are ignored and lookups always result in a
	miss.  However, regardless of the setting the cache is still
	invalidated when required when means you can safely toggle this on and
	off and the cache will always be "safe".
	Default: 1

cipso_cache_bucket_size - INTEGER
	The CIPSO label cache consists of a fixed size hash table with each
	hash bucket containing a number of cache entries.  This variable limits
	the number of entries in each hash bucket; the larger the value the
	more CIPSO label mappings that can be cached.  When the number of
	entries in a given hash bucket reaches this limit adding new entries
	causes the oldest entry in the bucket to be removed to make room.
	Default: 10

cipso_rbm_optfmt - BOOLEAN
	Enable the "Optimized Tag 1 Format" as defined in section 3.4.2.6 of
	the CIPSO draft specification (see Documentation/netlabel for details).
	This means that when set the CIPSO tag will be padded with empty
	categories in order to make the packet data 32-bit aligned.
	Default: 0

cipso_rbm_structvalid - BOOLEAN
	If set, do a very strict check of the CIPSO option when
	ip_options_compile() is called.  If unset, relax the checks done during
	ip_options_compile().  Either way is "safe" as errors are caught else
	where in the CIPSO processing code but setting this to 0 (False) should
	result in less work (i.e. it should be faster) but could cause problems
	with other implementations that require strict checking.
	Default: 0

IP Variables:

ip_local_port_range - 2 INTEGERS
	Defines the local port range that is used by TCP and UDP to
	choose the local port. The first number is the first, the 
	second the last local port number. Default value depends on
	amount of memory available on the system:
	> 128Mb 32768-61000
	< 128Mb 1024-4999 or even less.
	This number defines number of active connections, which this
	system can issue simultaneously to systems not supporting
	TCP extensions (timestamps). With tcp_tw_recycle enabled
	(i.e. by default) range 1024-4999 is enough to issue up to
	2000 connections per second to systems supporting timestamps.

ip_nonlocal_bind - BOOLEAN
	If set, allows processes to bind() to non-local IP addresses,
	which can be quite useful - but may break some applications.
	Default: 0

ip_dynaddr - BOOLEAN
	If set non-zero, enables support for dynamic addresses.
	If set to a non-zero value larger than 1, a kernel log
	message will be printed when dynamic address rewriting
	occurs.
	Default: 0

icmp_echo_ignore_all - BOOLEAN
	If set non-zero, then the kernel will ignore all ICMP ECHO
	requests sent to it.
	Default: 0

icmp_echo_ignore_broadcasts - BOOLEAN
	If set non-zero, then the kernel will ignore all ICMP ECHO and
	TIMESTAMP requests sent to it via broadcast/multicast.
	Default: 1

icmp_ratelimit - INTEGER
	Limit the maximal rates for sending ICMP packets whose type matches
	icmp_ratemask (see below) to specific targets.
	0 to disable any limiting, otherwise the maximal rate in jiffies(1)
	Default: 100

icmp_ratemask - INTEGER
	Mask made of ICMP types for which rates are being limited.
	Significant bits: IHGFEDCBA9876543210
	Default mask:     0000001100000011000 (6168)

	Bit definitions (see include/linux/icmp.h):
		0 Echo Reply
		3 Destination Unreachable *
		4 Source Quench *
		5 Redirect
		8 Echo Request
		B Time Exceeded *
		C Parameter Problem *
		D Timestamp Request
		E Timestamp Reply
		F Info Request
		G Info Reply
		H Address Mask Request
		I Address Mask Reply

	* These are rate limited by default (see default mask above)

icmp_ignore_bogus_error_responses - BOOLEAN
	Some routers violate RFC1122 by sending bogus responses to broadcast
	frames.  Such violations are normally logged via a kernel warning.
	If this is set to TRUE, the kernel will not give such warnings, which
	will avoid log file clutter.
	Default: FALSE

icmp_errors_use_inbound_ifaddr - BOOLEAN

	If zero, icmp error messages are sent with the primary address of
	the exiting interface.
 
	If non-zero, the message will be sent with the primary address of
	the interface that received the packet that caused the icmp error.
	This is the behaviour network many administrators will expect from
	a router. And it can make debugging complicated network layouts
	much easier. 

	Note that if no primary address exists for the interface selected,
	then the primary address of the first non-loopback interface that
	has one will be used regardless of this setting.

	Default: 0

igmp_max_memberships - INTEGER
	Change the maximum number of multicast groups we can subscribe to.
	Default: 20

conf/interface/*  changes special settings per interface (where "interface" is 
		  the name of your network interface)
conf/all/*	  is special, changes the settings for all interfaces


log_martians - BOOLEAN
	Log packets with impossible addresses to kernel log.
	log_martians for the interface will be enabled if at least one of
	conf/{all,interface}/log_martians is set to TRUE,
	it will be disabled otherwise

accept_redirects - BOOLEAN
	Accept ICMP redirect messages.
	accept_redirects for the interface will be enabled if:
	- both conf/{all,interface}/accept_redirects are TRUE in the case forwarding
	  for the interface is enabled
	or
	- at least one of conf/{all,interface}/accept_redirects is TRUE in the case
	  forwarding for the interface is disabled
	accept_redirects for the interface will be disabled otherwise
	default TRUE (host)
		FALSE (router)

forwarding - BOOLEAN
	Enable IP forwarding on this interface.

mc_forwarding - BOOLEAN
	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
	and a multicast routing daemon is required.
	conf/all/mc_forwarding must also be set to TRUE to enable multicast routing
	for the interface

medium_id - INTEGER
	Integer value used to differentiate the devices by the medium they
	are attached to. Two devices can have different id values when
	the broadcast packets are received only on one of them.
	The default value 0 means that the device is the only interface
	to its medium, value of -1 means that medium is not known.
	
	Currently, it is used to change the proxy_arp behavior:
	the proxy_arp feature is enabled for packets forwarded between
	two devices attached to different media.

proxy_arp - BOOLEAN
	Do proxy arp.
	proxy_arp for the interface will be enabled if at least one of
	conf/{all,interface}/proxy_arp is set to TRUE,
	it will be disabled otherwise

shared_media - BOOLEAN
	Send(router) or accept(host) RFC1620 shared media redirects.
	Overrides ip_secure_redirects.
	shared_media for the interface will be enabled if at least one of
	conf/{all,interface}/shared_media is set to TRUE,
	it will be disabled otherwise
	default TRUE

secure_redirects - BOOLEAN
	Accept ICMP redirect messages only for gateways,
	listed in default gateway list.
	secure_redirects for the interface will be enabled if at least one of
	conf/{all,interface}/secure_redirects is set to TRUE,
	it will be disabled otherwise
	default TRUE

send_redirects - BOOLEAN
	Send redirects, if router.
	send_redirects for the interface will be enabled if at least one of
	conf/{all,interface}/send_redirects is set to TRUE,
	it will be disabled otherwise
	Default: TRUE

bootp_relay - BOOLEAN
	Accept packets with source address 0.b.c.d destined
	not to this host as local ones. It is supposed, that
	BOOTP relay daemon will catch and forward such packets.
	conf/all/bootp_relay must also be set to TRUE to enable BOOTP relay
	for the interface
	default FALSE
	Not Implemented Yet.

accept_source_route - BOOLEAN
	Accept packets with SRR option.
	conf/all/accept_source_route must also be set to TRUE to accept packets
	with SRR option on the interface
	default TRUE (router)
		FALSE (host)

rp_filter - BOOLEAN
	1 - do source validation by reversed path, as specified in RFC1812
	    Recommended option for single homed hosts and stub network
	    routers. Could cause troubles for complicated (not loop free)
	    networks running a slow unreliable protocol (sort of RIP),
	    or using static routes.

	0 - No source validation.

	conf/all/rp_filter must also be set to TRUE to do source validation
	on the interface

	Default value is 0. Note that some distributions enable it
	in startup scripts.

arp_filter - BOOLEAN
	1 - Allows you to have multiple network interfaces on the same
	subnet, and have the ARPs for each interface be answered
	based on whether or not the kernel would route a packet from
	the ARP'd IP out that interface (therefore you must use source
	based routing for this to work). In other words it allows control
	of which cards (usually 1) will respond to an arp request.

	0 - (default) The kernel can respond to arp requests with addresses
	from other interfaces. This may seem wrong but it usually makes
	sense, because it increases the chance of successful communication.
	IP addresses are owned by the complete host on Linux, not by
	particular interfaces. Only for more complex setups like load-
	balancing, does this behaviour cause problems.

	arp_filter for the interface will be enabled if at least one of
	conf/{all,interface}/arp_filter is set to TRUE,
	it will be disabled otherwise

arp_announce - INTEGER
	Define different restriction levels for announcing the local
	source IP address from IP packets in ARP requests sent on
	interface:
	0 - (default) Use any local address, configured on any interface
	1 - Try to avoid local addresses that are not in the target's
	subnet for this interface. This mode is useful when target
	hosts reachable via this interface require the source IP
	address in ARP requests to be part of their logical network
	configured on the receiving interface. When we generate the
	request we will check all our subnets that include the
	target IP and will preserve the source address if it is from
	such subnet. If there is no such subnet we select source
	address according to the rules for level 2.
	2 - Always use the best local address for this target.
	In this mode we ignore the source address in the IP packet
	and try to select local address that we prefer for talks with
	the target host. Such local address is selected by looking
	for primary IP addresses on all our subnets on the outgoing
	interface that include the target IP address. If no suitable
	local address is found we select the first local address
	we have on the outgoing interface or on all other interfaces,
	with the hope we will receive reply for our request and
	even sometimes no matter the source IP address we announce.

	The max value from conf/{all,interface}/arp_announce is used.

	Increasing the restriction level gives more chance for
	receiving answer from the resolved target while decreasing
	the level announces more valid sender's information.

arp_ignore - INTEGER
	Define different modes for sending replies in response to
	received ARP requests that resolve local target IP addresses:
	0 - (default): reply for any local target IP address, configured
	on any interface
	1 - reply only if the target IP address is local address
	configured on the incoming interface
	2 - reply only if the target IP address is local address
	configured on the incoming interface and both with the
	sender's IP address are part from same subnet on this interface
	3 - do not reply for local addresses configured with scope host,
	only resolutions for global and link addresses are replied
	4-7 - reserved
	8 - do not reply for all local addresses

	The max value from conf/{all,interface}/arp_ignore is used
	when ARP request is received on the {interface}

arp_accept - BOOLEAN
	Define behavior when gratuitous arp replies are received:
	0 - drop gratuitous arp frames
	1 - accept gratuitous arp frames

app_solicit - INTEGER
	The maximum number of probes to send to the user space ARP daemon
	via netlink before dropping back to multicast probes (see
	mcast_solicit).  Defaults to 0.

disable_policy - BOOLEAN
	Disable IPSEC policy (SPD) for this interface

disable_xfrm - BOOLEAN
	Disable IPSEC encryption on this interface, whatever the policy



tag - INTEGER
	Allows you to write a number, which can be used as required.
	Default value is 0.

(1) Jiffie: internal timeunit for the kernel. On the i386 1/100s, on the
Alpha 1/1024s. See the HZ define in /usr/include/asm/param.h for the exact
value on your system. 

Alexey Kuznetsov.
kuznet@ms2.inr.ac.ru

Updated by:
Andi Kleen
ak@muc.de
Nicolas Delon
delon.nicolas@wanadoo.fr




/proc/sys/net/ipv6/* Variables:

IPv6 has no global variables such as tcp_*.  tcp_* settings under ipv4/ also
apply to IPv6 [XXX?].

bindv6only - BOOLEAN
	Default value for IPV6_V6ONLY socket option,
	which restricts use of the IPv6 socket to IPv6 communication 
	only.
		TRUE: disable IPv4-mapped address feature
		FALSE: enable IPv4-mapped address feature

	Default: FALSE (as specified in RFC2553bis)

IPv6 Fragmentation:

ip6frag_high_thresh - INTEGER
	Maximum memory used to reassemble IPv6 fragments. When 
	ip6frag_high_thresh bytes of memory is allocated for this purpose,
	the fragment handler will toss packets until ip6frag_low_thresh
	is reached.
	
ip6frag_low_thresh - INTEGER
	See ip6frag_high_thresh	

ip6frag_time - INTEGER
	Time in seconds to keep an IPv6 fragment in memory.

ip6frag_secret_interval - INTEGER
	Regeneration interval (in seconds) of the hash secret (or lifetime 
	for the hash secret) for IPv6 fragments.
	Default: 600

conf/default/*:
	Change the interface-specific default settings.


conf/all/*:
	Change all the interface-specific settings.  

	[XXX:  Other special features than forwarding?]

conf/all/forwarding - BOOLEAN
	Enable global IPv6 forwarding between all interfaces.  

	IPv4 and IPv6 work differently here; e.g. netfilter must be used 
	to control which interfaces may forward packets and which not.

	This also sets all interfaces' Host/Router setting 
	'forwarding' to the specified value.  See below for details.

	This referred to as global forwarding.

proxy_ndp - BOOLEAN
	Do proxy ndp.

conf/interface/*:
	Change special settings per interface.

	The functional behaviour for certain settings is different 
	depending on whether local forwarding is enabled or not.

accept_ra - BOOLEAN
	Accept Router Advertisements; autoconfigure using them.
	
	Functional default: enabled if local forwarding is disabled.
			    disabled if local forwarding is enabled.

accept_ra_defrtr - BOOLEAN
	Learn default router in Router Advertisement.

	Functional default: enabled if accept_ra is enabled.
			    disabled if accept_ra is disabled.

accept_ra_pinfo - BOOLEAN
	Learn Prefix Information in Router Advertisement.

	Functional default: enabled if accept_ra is enabled.
			    disabled if accept_ra is disabled.

accept_ra_rt_info_max_plen - INTEGER
	Maximum prefix length of Route Information in RA.

	Route Information w/ prefix larger than or equal to this
	variable shall be ignored.

	Functional default: 0 if accept_ra_rtr_pref is enabled.
			    -1 if accept_ra_rtr_pref is disabled.

accept_ra_rtr_pref - BOOLEAN
	Accept Router Preference in RA.

	Functional default: enabled if accept_ra is enabled.
			    disabled if accept_ra is disabled.

accept_redirects - BOOLEAN
	Accept Redirects.

	Functional default: enabled if local forwarding is disabled.
			    disabled if local forwarding is enabled.

accept_source_route - INTEGER
	Accept source routing (routing extension header).

	> 0: Accept routing header.
	= 0: Accept only routing header type 2.
	< 0: Do not accept routing header.

	Default: 0

autoconf - BOOLEAN
	Autoconfigure addresses using Prefix Information in Router 
	Advertisements.

	Functional default: enabled if accept_ra_pinfo is enabled.
			    disabled if accept_ra_pinfo is disabled.

dad_transmits - INTEGER
	The amount of Duplicate Address Detection probes to send.
	Default: 1
	
forwarding - BOOLEAN
	Configure interface-specific Host/Router behaviour.  

	Note: It is recommended to have the same setting on all 
	interfaces; mixed router/host scenarios are rather uncommon.

	FALSE:

	By default, Host behaviour is assumed.  This means:

	1. IsRouter flag is not set in Neighbour Advertisements.
	2. Router Solicitations are being sent when necessary.
	3. If accept_ra is TRUE (default), accept Router 
	   Advertisements (and do autoconfiguration).
	4. If accept_redirects is TRUE (default), accept Redirects.

	TRUE:

	If local forwarding is enabled, Router behaviour is assumed. 
	This means exactly the reverse from the above:

	1. IsRouter flag is set in Neighbour Advertisements.
	2. Router Solicitations are not sent.
	3. Router Advertisements are ignored.
	4. Redirects are ignored.

	Default: FALSE if global forwarding is disabled (default),
		 otherwise TRUE.

hop_limit - INTEGER
	Default Hop Limit to set.
	Default: 64

mtu - INTEGER
	Default Maximum Transfer Unit
	Default: 1280 (IPv6 required minimum)

router_probe_interval - INTEGER
	Minimum interval (in seconds) between Router Probing described
	in RFC4191.

	Default: 60

router_solicitation_delay - INTEGER
	Number of seconds to wait after interface is brought up
	before sending Router Solicitations.
	Default: 1

router_solicitation_interval - INTEGER
	Number of seconds to wait between Router Solicitations.
	Default: 4

router_solicitations - INTEGER
	Number of Router Solicitations to send until assuming no 
	routers are present.
	Default: 3

use_tempaddr - INTEGER
	Preference for Privacy Extensions (RFC3041).
	  <= 0 : disable Privacy Extensions
	  == 1 : enable Privacy Extensions, but prefer public
	         addresses over temporary addresses.
	  >  1 : enable Privacy Extensions and prefer temporary
	         addresses over public addresses.
	Default:  0 (for most devices)
		 -1 (for point-to-point devices and loopback devices)

temp_valid_lft - INTEGER
	valid lifetime (in seconds) for temporary addresses.
	Default: 604800 (7 days)

temp_prefered_lft - INTEGER
	Preferred lifetime (in seconds) for temporary addresses.
	Default: 86400 (1 day)

max_desync_factor - INTEGER
	Maximum value for DESYNC_FACTOR, which is a random value
	that ensures that clients don't synchronize with each 
	other and generate new addresses at exactly the same time.
	value is in seconds.
	Default: 600
	
regen_max_retry - INTEGER
	Number of attempts before give up attempting to generate
	valid temporary addresses.
	Default: 5

max_addresses - INTEGER
	Number of maximum addresses per interface.  0 disables limitation.
	It is recommended not set too large value (or 0) because it would 
	be too easy way to crash kernel to allow to create too much of 
	autoconfigured addresses.
	Default: 16

icmp/*:
ratelimit - INTEGER
	Limit the maximal rates for sending ICMPv6 packets.
	0 to disable any limiting, otherwise the maximal rate in jiffies(1)
	Default: 100


IPv6 Update by:
Pekka Savola <pekkas@netcore.fi>
YOSHIFUJI Hideaki / USAGI Project <yoshfuji@linux-ipv6.org>


/proc/sys/net/bridge/* Variables:

bridge-nf-call-arptables - BOOLEAN
	1 : pass bridged ARP traffic to arptables' FORWARD chain.
	0 : disable this.
	Default: 1

bridge-nf-call-iptables - BOOLEAN
	1 : pass bridged IPv4 traffic to iptables' chains.
	0 : disable this.
	Default: 1

bridge-nf-call-ip6tables - BOOLEAN
	1 : pass bridged IPv6 traffic to ip6tables' chains.
	0 : disable this.
	Default: 1

bridge-nf-filter-vlan-tagged - BOOLEAN
	1 : pass bridged vlan-tagged ARP/IP/IPv6 traffic to {arp,ip,ip6}tables.
	0 : disable this.
	Default: 1

bridge-nf-filter-pppoe-tagged - BOOLEAN
	1 : pass bridged pppoe-tagged IP/IPv6 traffic to {ip,ip6}tables.
	0 : disable this.
	Default: 1


UNDOCUMENTED:

dev_weight FIXME
discovery_slots FIXME
discovery_timeout FIXME
fast_poll_increase FIXME
ip6_queue_maxlen FIXME
lap_keepalive_time FIXME
lo_cong FIXME
max_baud_rate FIXME
max_dgram_qlen FIXME
max_noreply_time FIXME
max_tx_data_size FIXME
max_tx_window FIXME
min_tx_turn_time FIXME
mod_cong FIXME
no_cong FIXME
no_cong_thresh FIXME
slot_timeout FIXME
warn_noreply_time FIXME

title='author Bruce Allan <bruce.w.allan@intel.com> 2009-01-04 20:12:04 -0500 committer David S. Miller <davem@davemloft.net> 2009-01-04 20:12:04 -0500 e100: cosmetic cleanup' href='/cgit/cgit.cgi/litmus-rt.git/commit/drivers/net/e100.c?h=wip-splitting-omlp-jerickso&id=f26251eb68ea766a98fed922593c154d15127621'>f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4



f26251eb68ea
aaf918ba8cf9

1da177e4c3f4





962082b6df11
e6280f26b437
858119e15938
1da177e4c3f4







f26251eb68ea

1da177e4c3f4

f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4



f26251eb68ea
27345bb68414

1da177e4c3f4






858119e15938
1da177e4c3f4







f26251eb68ea
1da177e4c3f4








f26251eb68ea
1da177e4c3f4









f26251eb68ea

1da177e4c3f4





f26251eb68ea
962082b6df11


1da177e4c3f4












720017623ab2














1da177e4c3f4


ac7c66698a2c
1da177e4c3f4
ac7c66698a2c








27345bb68414
ac7c66698a2c








27345bb68414
1da177e4c3f4
ac7c66698a2c
1da177e4c3f4
27345bb68414
1da177e4c3f4

ac7c66698a2c
1da177e4c3f4





720017623ab2






















1da177e4c3f4

720017623ab2











































b55de80e4989
720017623ab2






1da177e4c3f4



2afecc047e90

1da177e4c3f4
1da177e4c3f4
44c10138fd4b
f26251eb68ea
1da177e4c3f4







0a0863af0d41
962082b6df11

1da177e4c3f4

7734f6e6bcd7
1172899a30d0
1da177e4c3f4

























720017623ab2

1da177e4c3f4



















f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4




f26251eb68ea
1da177e4c3f4

6bdacb1ad58b
f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4



44e4925e4601
1da177e4c3f4
44e4925e4601





1da177e4c3f4
44e4925e4601
1da177e4c3f4









2afecc047e90







0779bf2d2ecc
054799382037
2afecc047e90




054799382037
2afecc047e90








054799382037
2afecc047e90













054799382037
2afecc047e90







054799382037
2afecc047e90








9ac32e1bc051







2afecc047e90

9ac32e1bc051
2afecc047e90
44c10138fd4b
9ac32e1bc051





















2afecc047e90

9ac32e1bc051














241803332065

9ac32e1bc051

241803332065
9ac32e1bc051




























241803332065


9ac32e1bc051





241803332065
054799382037
241803332065











054799382037
3a4fa0a25da8
27345bb68414
241803332065





054799382037
241803332065
1da177e4c3f4















720017623ab2



































1da177e4c3f4











f26251eb68ea
1da177e4c3f4



f26251eb68ea
1da177e4c3f4

720017623ab2














1da177e4c3f4
b55de80e4989





1da177e4c3f4








f26251eb68ea
1da177e4c3f4






b55de80e4989


720017623ab2


b55de80e4989








60ffa478759f




648951451e6d
1da177e4c3f4










f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4
9ac32e1bc051
1da177e4c3f4
f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4














f26251eb68ea
1da177e4c3f4










f26251eb68ea
1da177e4c3f4



f26251eb68ea
1da177e4c3f4










09f75cd7bf13

1da177e4c3f4
aaf918ba8cf9

1da177e4c3f4


0a0863af0d41
1da177e4c3f4

f26251eb68ea
1da177e4c3f4









1da177e4c3f4





ecf7130b087a
1da177e4c3f4








f26251eb68ea
1da177e4c3f4



f26251eb68ea
1da177e4c3f4







054799382037
f26251eb68ea
1f53367d5d75
1da177e4c3f4






f26251eb68ea
1da177e4c3f4


f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4














f26251eb68ea
f4113030e73d



f26251eb68ea
f4113030e73d

1da177e4c3f4




054799382037



1da177e4c3f4
27345bb68414
1da177e4c3f4
ad8c48ad3bbe
1da177e4c3f4



f26251eb68ea
1da177e4c3f4


f26251eb68ea
1da177e4c3f4




34c6417b7087

1da177e4c3f4

858119e15938
1da177e4c3f4


962082b6df11
f26251eb68ea
996ec3533ae1
1da177e4c3f4





611494dccacb
1da177e4c3f4


3b29a56d31d5

1da177e4c3f4



f26251eb68ea
1da177e4c3f4


f26251eb68ea
1f53367d5d75
1da177e4c3f4




f26251eb68ea
1da177e4c3f4








5b548140225c
1da177e4c3f4


6ed106549d17
1da177e4c3f4

858119e15938
1da177e4c3f4
09f75cd7bf13
1da177e4c3f4




1da177e4c3f4
f26251eb68ea
1da177e4c3f4

dc45010e28bc



f26251eb68ea
09f75cd7bf13

1da177e4c3f4















f26251eb68ea
1da177e4c3f4






f26251eb68ea

1da177e4c3f4
f26251eb68ea
1da177e4c3f4






























f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4














ca93ca428b8e
1da177e4c3f4
f26251eb68ea

ca93ca428b8e

f26251eb68ea
ca93ca428b8e

f26251eb68ea
ca93ca428b8e


1da177e4c3f4


858119e15938
1da177e4c3f4
f26251eb68ea
1da177e4c3f4


1da177e4c3f4
27d7ff46a349
1da177e4c3f4


8d8bb39b9eba
1f53367d5d75
097688ef4710
1f53367d5d75



1da177e4c3f4
7734f6e6bcd7

aaf918ba8cf9
1da177e4c3f4
6caf52a453d5
1923815d855e
773c9c1f7717
1da177e4c3f4




858119e15938
1da177e4c3f4

09f75cd7bf13
1da177e4c3f4



f26251eb68ea
1da177e4c3f4



773c9c1f7717
1da177e4c3f4




7734f6e6bcd7








17393dd67c06
7734f6e6bcd7
303d67c28831

6ff9c2e7fa8c
1f53367d5d75
7734f6e6bcd7
1da177e4c3f4


f26251eb68ea
1da177e4c3f4



773c9c1f7717
1da177e4c3f4
7734f6e6bcd7








17393dd67c06
ca93ca428b8e
7734f6e6bcd7
ca93ca428b8e
1da177e4c3f4




f26251eb68ea
1da177e4c3f4
1da177e4c3f4
f26251eb68ea
1da177e4c3f4

1da177e4c3f4

09f75cd7bf13

1da177e4c3f4
f26251eb68ea
1da177e4c3f4







858119e15938
1da177e4c3f4


7734f6e6bcd7


1da177e4c3f4

f26251eb68ea
7734f6e6bcd7


ca93ca428b8e
1da177e4c3f4

7734f6e6bcd7











ca93ca428b8e
1da177e4c3f4
f26251eb68ea

1da177e4c3f4

ca93ca428b8e
7734f6e6bcd7
















773c9c1f7717
7734f6e6bcd7






773c9c1f7717
7734f6e6bcd7


773c9c1f7717
7734f6e6bcd7

f26251eb68ea
ca93ca428b8e
915e91d734d3
7734f6e6bcd7
f26251eb68ea
ca93ca428b8e

1da177e4c3f4






ca93ca428b8e

f26251eb68ea


1da177e4c3f4
773c9c1f7717
1da177e4c3f4







1da177e4c3f4





7734f6e6bcd7
1da177e4c3f4

ca93ca428b8e
1da177e4c3f4
f26251eb68ea
1da177e4c3f4
1da177e4c3f4
f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4



7734f6e6bcd7











773c9c1f7717
1da177e4c3f4

ca93ca428b8e
1da177e4c3f4



7d12e780e003
1da177e4c3f4


27345bb68414
1da177e4c3f4


f26251eb68ea
1da177e4c3f4



27345bb68414
1da177e4c3f4
ca93ca428b8e
f26251eb68ea
ca93ca428b8e

288379f05028
0685c31b58a6
288379f05028
0685c31b58a6
1da177e4c3f4



bea3348eef27
1da177e4c3f4
bea3348eef27
ddfce6bb43c6
1da177e4c3f4
bea3348eef27
53e52c729cc1
1da177e4c3f4
53e52c729cc1

288379f05028
1da177e4c3f4
1da177e4c3f4

bea3348eef27
1da177e4c3f4





611494dccacb
1da177e4c3f4
7d12e780e003
1da177e4c3f4




1da177e4c3f4















f26251eb68ea
1da177e4c3f4

















f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4

ca93ca428b8e
1da177e4c3f4
f26251eb68ea
1da177e4c3f4

1da177e4c3f4
bea3348eef27
0236ebb7ae85


1da177e4c3f4












0236ebb7ae85
bea3348eef27
0236ebb7ae85
1da177e4c3f4



1da177e4c3f4







054799382037
2acdb1e05c1a



c4028958b6ec
2acdb1e05c1a
c4028958b6ec

2acdb1e05c1a
1da177e4c3f4
27345bb68414
1da177e4c3f4













f26251eb68ea
1da177e4c3f4
f26251eb68ea
1da177e4c3f4


f26251eb68ea
1da177e4c3f4


f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4


ca93ca428b8e
1da177e4c3f4
f26251eb68ea
1da177e4c3f4








aa49cdd93be6
773c9c1f7717
aa49cdd93be6
f26251eb68ea
1da177e4c3f4





1da177e4c3f4
aa49cdd93be6
1da177e4c3f4





b55de80e4989


1da177e4c3f4








b55de80e4989



1da177e4c3f4
b55de80e4989







1da177e4c3f4






























abf9b902059f
1da177e4c3f4


abf9b902059f
1da177e4c3f4








44c10138fd4b
27345bb68414


f26251eb68ea
1da177e4c3f4



















bc79fc8409b3

1da177e4c3f4

f26251eb68ea
1da177e4c3f4



bc79fc8409b3

1da177e4c3f4



















































f26251eb68ea
1da177e4c3f4































054799382037
1da177e4c3f4

f26251eb68ea
1da177e4c3f4






f26251eb68ea
1da177e4c3f4











4c3616cdda06
1da177e4c3f4
1da177e4c3f4









f26251eb68ea
1da177e4c3f4



f26251eb68ea
1da177e4c3f4







f26251eb68ea
1da177e4c3f4

f26251eb68ea
1da177e4c3f4
a074fb860846

1da177e4c3f4




b55de80e4989

1da177e4c3f4
f26251eb68ea
1da177e4c3f4



b55de80e4989
1da177e4c3f4
















4c3616cdda06
1da177e4c3f4
b9f2c0440d80
1da177e4c3f4
b9f2c0440d80







1da177e4c3f4







f26251eb68ea
09f75cd7bf13
1da177e4c3f4












f26251eb68ea
1da177e4c3f4








7282d491ecae
1da177e4c3f4















1da177e4c3f4


1da177e4c3f4
b9f2c0440d80
1da177e4c3f4

















f26251eb68ea
1da177e4c3f4











f26251eb68ea
1da177e4c3f4









acc784263b0c


008298231abb
acc784263b0c










1da177e4c3f4






f26251eb68ea

1da177e4c3f4



acc784263b0c
1da177e4c3f4
1da177e4c3f4
0eb5a34cdf34
1da177e4c3f4

bea3348eef27
1da177e4c3f4


720017623ab2
1da177e4c3f4

f26251eb68ea
1da177e4c3f4



f26251eb68ea
1da177e4c3f4





f26251eb68ea
1da177e4c3f4



284901a90a9e
1da177e4c3f4



1da177e4c3f4

27345bb68414



f26251eb68ea
1da177e4c3f4




f26251eb68ea
1da177e4c3f4





1f53367d5d75
1da177e4c3f4

ac7c66698a2c
1da177e4c3f4














c4028958b6ec
2acdb1e05c1a
f26251eb68ea
1da177e4c3f4



f26251eb68ea
1da177e4c3f4

f92d87287661

1da177e4c3f4
a92dd9233ad1
948cd43fed7c









1da177e4c3f4


f26251eb68ea
bc79fc8409b3
1da177e4c3f4
bc79fc8409b3

1da177e4c3f4
6bdacb1ad58b
e7272403d2f9
1da177e4c3f4

f26251eb68ea
1da177e4c3f4



e174961ca1a0
0795af5729b1
e174961ca1a0
1da177e4c3f4





27345bb68414
1da177e4c3f4













f26251eb68ea
1da177e4c3f4


915e91d734d3
1da177e4c3f4






b55de80e4989


ac7c992cac0c
1da177e4c3f4



824545e70315
f902283bbe68
518d83382568
a53a33da864a
1da177e4c3f4
e8e82b76e031

b55de80e4989








ac7c992cac0c
e8e82b76e031
ac7c992cac0c
e8e82b76e031
975b366af662
8543da6672b0
ac7c992cac0c
1da177e4c3f4
ac7c992cac0c

6905b1f1a03a
ac7c992cac0c
6905b1f1a03a




1da177e4c3f4

f902283bbe68
ac7c992cac0c






1da177e4c3f4




975b366af662
1da177e4c3f4
6bdacb1ad58b
975b366af662
1da177e4c3f4
4b512d26f425
b55de80e4989








1da177e4c3f4
975b366af662
1da177e4c3f4



975b366af662
1da177e4c3f4
d18c3db58bc5
6bdacb1ad58b
ac7c992cac0c



6bdacb1ad58b

2cc304923d87



0a0863af0d41
2cc304923d87



bea3348eef27
2cc304923d87
2cc304923d87
ef681ce1e8b3





b1d26f24e864
2cc304923d87

























































6bdacb1ad58b
1da177e4c3f4




e8e82b76e031
975b366af662
1da177e4c3f4


054799382037
2cc304923d87
1da177e4c3f4



f26251eb68ea
1da177e4c3f4


299176206b26
1da177e4c3f4








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062

                                                                                

                                             

                                                                         

                                                                   
 
                                                                        

                                                                           
               
 
                                                                              

                                                                    
 

                                                                         
 

                                   
                                                              







































































                                                                                
                    










                                                                         






                                                                            






                                                                          
                                                                        

















                                                                         



                                                                       

                                                                          

   







                              
                              






                              
                           



                                      
                                       
                                                  
                                                                 
                                                                          




                                             



                                                      



                                    


                                

                     
                                     
                      
                            
                                            
                             
                                                           
                                                                      
                                                         


                                                                     
                                    


































                                                                 




                                               
                                               




                                               
                                               




























                                        
                                  




















                                    
                                



                                





                              

































                                                                           
 



























                                 
                                 








                                     











                       





























                               





                           





















































                                                                               
                     





                                                                


                       

                                    
                                         







                                           

                                                


                                        
                                        










                                            
                                                                     

                                                                             
                                                                  

                                                                     


                                                              


























                                                                           
                                                                                




                                                                      
                                 





                                                                      
                                



                               
                          












                                                                         


                                      
                                           




















                                   

                      
                           
                             





                                                                 
                                             

 
                                            



                                                 
                                                       
                              
                                                      

 
                                             



                                                 
                                                      
                              
                                                      





                                                                
                                                    


                                          
                                                   















                                                                      
                                                        







                                                    
                                             



                                                                     
                                                






                                                                  
                                                                                   







                                                                             
                                  


                                                     
                                 

                                 
                                                                 

                                                 
                                           

                                                              
                                                                  

                                                         
                                                                         





                                                         
                                                       




                                                                     
                                                                        








                                                              
                                                         


                                               
                                   
                                                                       
                                                          
                                                 
 
                                                                 
                                                 
 

                                                                     
                                                          
                                               


                                              
 



                                                           
                                               

                                         
                                 










                                                                            
                                                       
                                                                           
                                              
                                                                   



                                                                         
                                                                                
                                                          

                                           













                                                                            
                                            

                               
                                                        



                                                                          
                                                         

                                                                         





                                                            
                                                                        
                                                                 
                                                                      







                                                          

                                                            

                              
                                                     

                                  
                                                   



                                
                                        

                                                            






                                                      
                                                             







                                                                        
                                        








                                  
                                      









                                                                       

                                                             





                                                                      
                                             


                                                                     












                                                                














                                                                              


                         
                            
 








                                                                    
                                                              








                                                                              
                                                                                
 
                                   
                           
                                                                           

                              
                                                       





                                                                               






















                                                                                

 











































                                                                              
         






                                                              



                                              

                                                                          
 
                                                                               
                                                                              
                                    







                                                                       
                                                                            

                                                                   

                                                  
                                   
                                                     

























                                                                               

                                                                               



















                                                                               
                                                         

                                                                             
                                                        




                                                                               
                                       

                                                                            
                                 
                                                                    

                                                                         
                                            



                                                                             
                                                  
                                                                              





                                                                               
                                                            
                 









                                                                               







                                                                          
                                                                   
                                                               




                                                                   
              








                                                                        
                













                                                                          
                                                                     







                                                                          
                                                                        








                                                         







                                                                    

                                                
                            
 
                                                         





















                                                                           

         














                                                                            

 

                                                            
 




























                                                                              


                                         





                                                                    
                                                                            
 











                                                          
 
                                                               
                                              





                                                                    
 
                   















                                                                          



































                                                                              











                                                                           
                                           



                                                                           
                                                                        

                              














                                                                               
 





                                                                 








                                                                
                                                            






                                                                        


                                                                               


                                                                 








                                                                               




                                                                                
         










                                           
                                                           

                           
                                       
                           
                                                         
                           
                                                         
                           
                                              
                           
                                                            
                           
                                                               
                           
                                                    

                                                              
                                                          














                                                                           
                                                              










                                                                      
                                        



                                           
                                           










                                                            

                                                  
                                           

                                                                              


                                                                    
                                                               

                               
                                                                









                                                                           





                                                                               
                                                                           








                                                                
                                                    



                                                                         
                                                          







                                                                       
 
                                                  
                                                                       






                                                                            
                                    


                                                                   
                                                                 
                                                   
                                                   

                                                         
                                                   

                                                       
                                              














                                                                
                                                                       



                                                                               
                                                                              

                                                               




                                                                 



                                                                           
                                      
                                                                                    
                              
                                        



                                                             
                                         


                                                                           
                                                                               




                                                                               

                                                                 

 
                                                             


                                      
                                                            
                                                     
                                                 





                                                                            
                                        


                                                   

                                                             



                                              
                                              


                                                                       
                                                   
                                                                        




                                                        
                      








                                                                               
                                      


                                      
                            

 
                                         
 
                                             




                                 
                                       
                                   

                                                  



                                                                               
                                              

                                                            















                                                                    
                                                                     






                                              

                                                                 
                                                         
                                      






























                                                                            
                      

                               
                                                          














                                                                         
                                                                      
 

                                                    

                                     
                               

                                                                   
                      


                                                            


                                                             
                                                            
 
                                                                                   


                                           
                                           
                                                                              


                                                               
                                                             
                                           
                               



                                 
                                                                

                                                                          
                            
                                                                         
                                                                  
                                                                             
                                                                   




                 
                                                           

                                                         
                                             



                                                  
                                                            



                                                                  
                                                           




                                                                 








                                                                               
                                                                        
                                                               

                                                                       
                                                                   
                                
         


                                                             
                                                                     



                                                               
                                                    
 








                                                                         
                                                            
                                               
         
 




                                                                      
                                              
                                                                 
                                       
                                                                

                                                     

                                       

                                                   
                                       
                              







                                       
                                                                   


                                


                                                              

                                            
                                                                                


                                                                       
                              

         











                                                                            
 
                                           

                                                                             

                                                                         
 
















                                                                               
                                               






                                                                              
                                               


                                                                            
                                               

         
                               
                               
                                                                
                                                           
                              

                                       






                                                       

                                           


                                                                  
                                                                         
                                                                            







                                                       





                                                       
                                

                                                 
                                           
 
                                                                        
                               
 
                                                          

                                                                    
                                                 



                                                











                                                                              
                                                           

                                                     
                                       



                 
                                                   


                                              
                                                       


                                                              
                                                                       



                                                                         
                                                    
 
                                                                         
                                    

                                               
                                                     
                                      
                                            
         



                           
                                                          
 
                                                               
                                   
 
                                               
                           
 

                                                                 
                                    
                                     

         
                         





                                                   
 
                              
                                          




                             















                                                                   
                                                         

















                                                                                
                                            
                           
                                        
                                       
                                      

                                             
                                       
                                           
                                                                      

                                                 
                                      
                                


                                                                       












                                       
                                            
                                 
                                      



                                              







                                                      
                                                                   



                                             
                                                          
 

                                                                          
 
                                                     
                                                













                                                                           
                                            
                           
                                        


                                                                   
                                                        


                                       
                                      

                                       
                                    


                                                                  
                                       
 
                                                                   








                                              
                                                                          
                                                            
 
                                                                    





                                                              
                            
                           





                                


                                                                      








                                              



                                                  
 







                                                                       






























                                                                                
                          


                                                       
                                                              








                                                    
                                                        


                                                        
                                            



















                                                                                

                                                           

                                   
                         



                                         

                                                                



















































                                                                         
                                               































                                                                         
                                                                

                               
                                  






                                                                  
                                  











                                                           
                                                      
 









                                                     
                                                



                                                           
                                          







                                                              
                                          

                                     
                                           
                                                                

                                       




                                                            

                                                                           
 
                                                             



                                                        
                                                        
















                                                                           
                                                       
 
                                                                   
 







                                      







                                                             
                                                
                                                               












                                                                                
                            








                                                                                
                                                    















                                                      


                                                   
                                                         
                                                      

















                                                                               
                       











                                                                  
                                 









                                                                         


                                                      
                                                  










                                                          






                                                     

                                                             



                                                                               
                                              
                                                   
                                                      
                                                                        

                                  
                                                                        


                                           
                                      

                                      
                                              



                                                                             
                                                              





                                                                    
                                                          



                                                                                
                                                               



                                                                                

                                           



                                                                         
                        




                                                                                
                             





                                   
                                                               

                                       
                                        














                                                                             
                                                               
 
                                      



                                                                               
                                          

                                  

                           
                                                        
                                                         









                                                                               


                                                         
                                              
                                                      
                                        

                                                           
 
                                                      
                                    

                                      
                                              



                                                                               
                                                                   
                                                                             
                                             





                       
                                    













                                                          
                     


                                                      
                                            






                                            


                                                                     
                                                                    



                                                          
                                  
                               
                                    
 
                             

                                                       








                                                                              
                                    
                
                                     
         
 
                                 
 
 

                                                            
                 
                                                  




                                             

 
                






                                                                 




                                                          
                                          
                                
                                                      
                                    
 
                                              








                                                                   
                                    
                                  



                             
                      
 
                                               
 



                                             

 



                                                                          
                                           



                                                                                               
                                              
 
                                    





                                                 
                                 

























































                                                                                    
 




                                                 
                
                                    


                                     
                                      
                                         



                                        
                                                 


                                                                               
                                                 








                                            
/*******************************************************************************

  Intel PRO/100 Linux driver
  Copyright(c) 1999 - 2006 Intel Corporation.

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Contact Information:
  Linux NICS <linux.nics@intel.com>
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497

*******************************************************************************/

/*
 *	e100.c: Intel(R) PRO/100 ethernet driver
 *
 *	(Re)written 2003 by scott.feldman@intel.com.  Based loosely on
 *	original e100 driver, but better described as a munging of
 *	e100, e1000, eepro100, tg3, 8139cp, and other drivers.
 *
 *	References:
 *		Intel 8255x 10/100 Mbps Ethernet Controller Family,
 *		Open Source Software Developers Manual,
 *		http://sourceforge.net/projects/e1000
 *
 *
 *	                      Theory of Operation
 *
 *	I.   General
 *
 *	The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet
 *	controller family, which includes the 82557, 82558, 82559, 82550,
 *	82551, and 82562 devices.  82558 and greater controllers
 *	integrate the Intel 82555 PHY.  The controllers are used in
 *	server and client network interface cards, as well as in
 *	LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx
 *	configurations.  8255x supports a 32-bit linear addressing
 *	mode and operates at 33Mhz PCI clock rate.
 *
 *	II.  Driver Operation
 *
 *	Memory-mapped mode is used exclusively to access the device's
 *	shared-memory structure, the Control/Status Registers (CSR). All
 *	setup, configuration, and control of the device, including queuing
 *	of Tx, Rx, and configuration commands is through the CSR.
 *	cmd_lock serializes accesses to the CSR command register.  cb_lock
 *	protects the shared Command Block List (CBL).
 *
 *	8255x is highly MII-compliant and all access to the PHY go
 *	through the Management Data Interface (MDI).  Consequently, the
 *	driver leverages the mii.c library shared with other MII-compliant
 *	devices.
 *
 *	Big- and Little-Endian byte order as well as 32- and 64-bit
 *	archs are supported.  Weak-ordered memory and non-cache-coherent
 *	archs are supported.
 *
 *	III. Transmit
 *
 *	A Tx skb is mapped and hangs off of a TCB.  TCBs are linked
 *	together in a fixed-size ring (CBL) thus forming the flexible mode
 *	memory structure.  A TCB marked with the suspend-bit indicates
 *	the end of the ring.  The last TCB processed suspends the
 *	controller, and the controller can be restarted by issue a CU
 *	resume command to continue from the suspend point, or a CU start
 *	command to start at a given position in the ring.
 *
 *	Non-Tx commands (config, multicast setup, etc) are linked
 *	into the CBL ring along with Tx commands.  The common structure
 *	used for both Tx and non-Tx commands is the Command Block (CB).
 *
 *	cb_to_use is the next CB to use for queuing a command; cb_to_clean
 *	is the next CB to check for completion; cb_to_send is the first
 *	CB to start on in case of a previous failure to resume.  CB clean
 *	up happens in interrupt context in response to a CU interrupt.
 *	cbs_avail keeps track of number of free CB resources available.
 *
 * 	Hardware padding of short packets to minimum packet size is
 * 	enabled.  82557 pads with 7Eh, while the later controllers pad
 * 	with 00h.
 *
 *	IV.  Receive
 *
 *	The Receive Frame Area (RFA) comprises a ring of Receive Frame
 *	Descriptors (RFD) + data buffer, thus forming the simplified mode
 *	memory structure.  Rx skbs are allocated to contain both the RFD
 *	and the data buffer, but the RFD is pulled off before the skb is
 *	indicated.  The data buffer is aligned such that encapsulated
 *	protocol headers are u32-aligned.  Since the RFD is part of the
 *	mapped shared memory, and completion status is contained within
 *	the RFD, the RFD must be dma_sync'ed to maintain a consistent
 *	view from software and hardware.
 *
 *	In order to keep updates to the RFD link field from colliding with
 *	hardware writes to mark packets complete, we use the feature that
 *	hardware will not write to a size 0 descriptor and mark the previous
 *	packet as end-of-list (EL).   After updating the link, we remove EL
 *	and only then restore the size such that hardware may use the
 *	previous-to-end RFD.
 *
 *	Under typical operation, the  receive unit (RU) is start once,
 *	and the controller happily fills RFDs as frames arrive.  If
 *	replacement RFDs cannot be allocated, or the RU goes non-active,
 *	the RU must be restarted.  Frame arrival generates an interrupt,
 *	and Rx indication and re-allocation happen in the same context,
 *	therefore no locking is required.  A software-generated interrupt
 *	is generated from the watchdog to recover from a failed allocation
 *	scenario where all Rx resources have been indicated and none re-
 *	placed.
 *
 *	V.   Miscellaneous
 *
 * 	VLAN offloading of tagging, stripping and filtering is not
 * 	supported, but driver will accommodate the extra 4-byte VLAN tag
 * 	for processing by upper layers.  Tx/Rx Checksum offloading is not
 * 	supported.  Tx Scatter/Gather is not supported.  Jumbo Frames is
 * 	not supported (hardware limitation).
 *
 * 	MagicPacket(tm) WoL support is enabled/disabled via ethtool.
 *
 * 	Thanks to JC (jchapman@katalix.com) for helping with
 * 	testing/troubleshooting the development driver.
 *
 * 	TODO:
 * 	o several entry points race with dev->close
 * 	o check for tx-no-resources/stop Q races with tx clean/wake Q
 *
 *	FIXES:
 * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
 *	- Stratus87247: protect MDI control register manipulations
 * 2009/06/01 - Andreas Mohr <andi at lisas dot de>
 *      - add clean lowlevel I/O emulation for cards with MII-lacking PHYs
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/string.h>
#include <linux/firmware.h>
#include <asm/unaligned.h>


#define DRV_NAME		"e100"
#define DRV_EXT			"-NAPI"
#define DRV_VERSION		"3.5.24-k2"DRV_EXT
#define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT		"Copyright(c) 1999-2006 Intel Corporation"
#define PFX			DRV_NAME ": "

#define E100_WATCHDOG_PERIOD	(2 * HZ)
#define E100_NAPI_WEIGHT	16

#define FIRMWARE_D101M		"e100/d101m_ucode.bin"
#define FIRMWARE_D101S		"e100/d101s_ucode.bin"
#define FIRMWARE_D102E		"e100/d102e_ucode.bin"

MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_FIRMWARE(FIRMWARE_D101M);
MODULE_FIRMWARE(FIRMWARE_D101S);
MODULE_FIRMWARE(FIRMWARE_D102E);

static int debug = 3;
static int eeprom_bad_csum_allow = 0;
static int use_io = 0;
module_param(debug, int, 0);
module_param(eeprom_bad_csum_allow, int, 0);
module_param(use_io, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");
MODULE_PARM_DESC(use_io, "Force use of i/o access mode");
#define DPRINTK(nlevel, klevel, fmt, args...) \
	(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
	printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
		__func__ , ## args))

#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
	PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
	PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
static struct pci_device_id e100_id_table[] = {
	INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
	INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
	INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
	INTEL_8255X_ETHERNET_DEVICE(0x1032, 3),
	INTEL_8255X_ETHERNET_DEVICE(0x1033, 3),
	INTEL_8255X_ETHERNET_DEVICE(0x1034, 3),
	INTEL_8255X_ETHERNET_DEVICE(0x1038, 3),
	INTEL_8255X_ETHERNET_DEVICE(0x1039, 4),
	INTEL_8255X_ETHERNET_DEVICE(0x103A, 4),
	INTEL_8255X_ETHERNET_DEVICE(0x103B, 4),
	INTEL_8255X_ETHERNET_DEVICE(0x103C, 4),
	INTEL_8255X_ETHERNET_DEVICE(0x103D, 4),
	INTEL_8255X_ETHERNET_DEVICE(0x103E, 4),
	INTEL_8255X_ETHERNET_DEVICE(0x1050, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1051, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1052, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1056, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1057, 5),
	INTEL_8255X_ETHERNET_DEVICE(0x1059, 0),
	INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x1067, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x1068, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x1069, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x106A, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x106B, 6),
	INTEL_8255X_ETHERNET_DEVICE(0x1091, 7),
	INTEL_8255X_ETHERNET_DEVICE(0x1092, 7),
	INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
	INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
	INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
	INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7),
	INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
	INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
	INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
	INTEL_8255X_ETHERNET_DEVICE(0x2459, 2),
	INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
	INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7),
	{ 0, }
};
MODULE_DEVICE_TABLE(pci, e100_id_table);

enum mac {
	mac_82557_D100_A  = 0,
	mac_82557_D100_B  = 1,
	mac_82557_D100_C  = 2,
	mac_82558_D101_A4 = 4,
	mac_82558_D101_B0 = 5,
	mac_82559_D101M   = 8,
	mac_82559_D101S   = 9,
	mac_82550_D102    = 12,
	mac_82550_D102_C  = 13,
	mac_82551_E       = 14,
	mac_82551_F       = 15,
	mac_82551_10      = 16,
	mac_unknown       = 0xFF,
};

enum phy {
	phy_100a     = 0x000003E0,
	phy_100c     = 0x035002A8,
	phy_82555_tx = 0x015002A8,
	phy_nsc_tx   = 0x5C002000,
	phy_82562_et = 0x033002A8,
	phy_82562_em = 0x032002A8,
	phy_82562_ek = 0x031002A8,
	phy_82562_eh = 0x017002A8,
	phy_82552_v  = 0xd061004d,
	phy_unknown  = 0xFFFFFFFF,
};

/* CSR (Control/Status Registers) */
struct csr {
	struct {
		u8 status;
		u8 stat_ack;
		u8 cmd_lo;
		u8 cmd_hi;
		u32 gen_ptr;
	} scb;
	u32 port;
	u16 flash_ctrl;
	u8 eeprom_ctrl_lo;
	u8 eeprom_ctrl_hi;
	u32 mdi_ctrl;
	u32 rx_dma_count;
};

enum scb_status {
	rus_no_res       = 0x08,
	rus_ready        = 0x10,
	rus_mask         = 0x3C,
};

enum ru_state  {
	RU_SUSPENDED = 0,
	RU_RUNNING	 = 1,
	RU_UNINITIALIZED = -1,
};

enum scb_stat_ack {
	stat_ack_not_ours    = 0x00,
	stat_ack_sw_gen      = 0x04,
	stat_ack_rnr         = 0x10,
	stat_ack_cu_idle     = 0x20,
	stat_ack_frame_rx    = 0x40,
	stat_ack_cu_cmd_done = 0x80,
	stat_ack_not_present = 0xFF,
	stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
	stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
};

enum scb_cmd_hi {
	irq_mask_none = 0x00,
	irq_mask_all  = 0x01,
	irq_sw_gen    = 0x02,
};

enum scb_cmd_lo {
	cuc_nop        = 0x00,
	ruc_start      = 0x01,
	ruc_load_base  = 0x06,
	cuc_start      = 0x10,
	cuc_resume     = 0x20,
	cuc_dump_addr  = 0x40,
	cuc_dump_stats = 0x50,
	cuc_load_base  = 0x60,
	cuc_dump_reset = 0x70,
};

enum cuc_dump {
	cuc_dump_complete       = 0x0000A005,
	cuc_dump_reset_complete = 0x0000A007,
};

enum port {
	software_reset  = 0x0000,
	selftest        = 0x0001,
	selective_reset = 0x0002,
};

enum eeprom_ctrl_lo {
	eesk = 0x01,
	eecs = 0x02,
	eedi = 0x04,
	eedo = 0x08,
};

enum mdi_ctrl {
	mdi_write = 0x04000000,
	mdi_read  = 0x08000000,
	mdi_ready = 0x10000000,
};

enum eeprom_op {
	op_write = 0x05,
	op_read  = 0x06,
	op_ewds  = 0x10,
	op_ewen  = 0x13,
};

enum eeprom_offsets {
	eeprom_cnfg_mdix  = 0x03,
	eeprom_phy_iface  = 0x06,
	eeprom_id         = 0x0A,
	eeprom_config_asf = 0x0D,
	eeprom_smbus_addr = 0x90,
};

enum eeprom_cnfg_mdix {
	eeprom_mdix_enabled = 0x0080,
};

enum eeprom_phy_iface {
	NoSuchPhy = 0,
	I82553AB,
	I82553C,
	I82503,
	DP83840,
	S80C240,
	S80C24,
	I82555,
	DP83840A = 10,
};

enum eeprom_id {
	eeprom_id_wol = 0x0020,
};

enum eeprom_config_asf {
	eeprom_asf = 0x8000,
	eeprom_gcl = 0x4000,
};

enum cb_status {
	cb_complete = 0x8000,
	cb_ok       = 0x2000,
};

enum cb_command {
	cb_nop    = 0x0000,
	cb_iaaddr = 0x0001,
	cb_config = 0x0002,
	cb_multi  = 0x0003,
	cb_tx     = 0x0004,
	cb_ucode  = 0x0005,
	cb_dump   = 0x0006,
	cb_tx_sf  = 0x0008,
	cb_cid    = 0x1f00,
	cb_i      = 0x2000,
	cb_s      = 0x4000,
	cb_el     = 0x8000,
};

struct rfd {
	__le16 status;
	__le16 command;
	__le32 link;
	__le32 rbd;
	__le16 actual_size;
	__le16 size;
};

struct rx {
	struct rx *next, *prev;
	struct sk_buff *skb;
	dma_addr_t dma_addr;
};

#if defined(__BIG_ENDIAN_BITFIELD)
#define X(a,b)	b,a
#else
#define X(a,b)	a,b
#endif
struct config {
/*0*/	u8 X(byte_count:6, pad0:2);
/*1*/	u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1);
/*2*/	u8 adaptive_ifs;
/*3*/	u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1),
	   term_write_cache_line:1), pad3:4);
/*4*/	u8 X(rx_dma_max_count:7, pad4:1);
/*5*/	u8 X(tx_dma_max_count:7, dma_max_count_enable:1);
/*6*/	u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1),
	   tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1),
	   rx_discard_overruns:1), rx_save_bad_frames:1);
/*7*/	u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2),
	   pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1),
	   tx_dynamic_tbd:1);
/*8*/	u8 X(X(mii_mode:1, pad8:6), csma_disabled:1);
/*9*/	u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1),
	   link_status_wake:1), arp_wake:1), mcmatch_wake:1);
/*10*/	u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2),
	   loopback:2);
/*11*/	u8 X(linear_priority:3, pad11:5);
/*12*/	u8 X(X(linear_priority_mode:1, pad12:3), ifs:4);
/*13*/	u8 ip_addr_lo;
/*14*/	u8 ip_addr_hi;
/*15*/	u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1),
	   wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1),
	   pad15_2:1), crs_or_cdt:1);
/*16*/	u8 fc_delay_lo;
/*17*/	u8 fc_delay_hi;
/*18*/	u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1),
	   rx_long_ok:1), fc_priority_threshold:3), pad18:1);
/*19*/	u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1),
	   fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1),
	   full_duplex_force:1), full_duplex_pin:1);
/*20*/	u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1);
/*21*/	u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4);
/*22*/	u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6);
	u8 pad_d102[9];
};

#define E100_MAX_MULTICAST_ADDRS	64
struct multi {
	__le16 count;
	u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/];
};

/* Important: keep total struct u32-aligned */
#define UCODE_SIZE			134
struct cb {
	__le16 status;
	__le16 command;
	__le32 link;
	union {
		u8 iaaddr[ETH_ALEN];
		__le32 ucode[UCODE_SIZE];
		struct config config;
		struct multi multi;
		struct {
			u32 tbd_array;
			u16 tcb_byte_count;
			u8 threshold;
			u8 tbd_count;
			struct {
				__le32 buf_addr;
				__le16 size;
				u16 eol;
			} tbd;
		} tcb;
		__le32 dump_buffer_addr;
	} u;
	struct cb *next, *prev;
	dma_addr_t dma_addr;
	struct sk_buff *skb;
};

enum loopback {
	lb_none = 0, lb_mac = 1, lb_phy = 3,
};

struct stats {
	__le32 tx_good_frames, tx_max_collisions, tx_late_collisions,
		tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
		tx_multiple_collisions, tx_total_collisions;
	__le32 rx_good_frames, rx_crc_errors, rx_alignment_errors,
		rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
		rx_short_frame_errors;
	__le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
	__le16 xmt_tco_frames, rcv_tco_frames;
	__le32 complete;
};

struct mem {
	struct {
		u32 signature;
		u32 result;
	} selftest;
	struct stats stats;
	u8 dump_buf[596];
};

struct param_range {
	u32 min;
	u32 max;
	u32 count;
};

struct params {
	struct param_range rfds;
	struct param_range cbs;
};

struct nic {
	/* Begin: frequently used values: keep adjacent for cache effect */
	u32 msg_enable				____cacheline_aligned;
	struct net_device *netdev;
	struct pci_dev *pdev;
	u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data);

	struct rx *rxs				____cacheline_aligned;
	struct rx *rx_to_use;
	struct rx *rx_to_clean;
	struct rfd blank_rfd;
	enum ru_state ru_running;

	spinlock_t cb_lock			____cacheline_aligned;
	spinlock_t cmd_lock;
	struct csr __iomem *csr;
	enum scb_cmd_lo cuc_cmd;
	unsigned int cbs_avail;
	struct napi_struct napi;
	struct cb *cbs;
	struct cb *cb_to_use;
	struct cb *cb_to_send;
	struct cb *cb_to_clean;
	__le16 tx_command;
	/* End: frequently used values: keep adjacent for cache effect */

	enum {
		ich                = (1 << 0),
		promiscuous        = (1 << 1),
		multicast_all      = (1 << 2),
		wol_magic          = (1 << 3),
		ich_10h_workaround = (1 << 4),
	} flags					____cacheline_aligned;

	enum mac mac;
	enum phy phy;
	struct params params;
	struct timer_list watchdog;
	struct timer_list blink_timer;
	struct mii_if_info mii;
	struct work_struct tx_timeout_task;
	enum loopback loopback;

	struct mem *mem;
	dma_addr_t dma_addr;

	dma_addr_t cbs_dma_addr;
	u8 adaptive_ifs;
	u8 tx_threshold;
	u32 tx_frames;
	u32 tx_collisions;
	u32 tx_deferred;
	u32 tx_single_collisions;
	u32 tx_multiple_collisions;
	u32 tx_fc_pause;
	u32 tx_tco_frames;

	u32 rx_fc_pause;
	u32 rx_fc_unsupported;
	u32 rx_tco_frames;
	u32 rx_over_length_errors;

	u16 leds;
	u16 eeprom_wc;
	__le16 eeprom[256];
	spinlock_t mdio_lock;
};

static inline void e100_write_flush(struct nic *nic)
{
	/* Flush previous PCI writes through intermediate bridges
	 * by doing a benign read */
	(void)ioread8(&nic->csr->scb.status);
}

static void e100_enable_irq(struct nic *nic)
{
	unsigned long flags;

	spin_lock_irqsave(&nic->cmd_lock, flags);
	iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi);
	e100_write_flush(nic);
	spin_unlock_irqrestore(&nic->cmd_lock, flags);
}

static void e100_disable_irq(struct nic *nic)
{
	unsigned long flags;

	spin_lock_irqsave(&nic->cmd_lock, flags);
	iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi);
	e100_write_flush(nic);
	spin_unlock_irqrestore(&nic->cmd_lock, flags);
}

static void e100_hw_reset(struct nic *nic)
{
	/* Put CU and RU into idle with a selective reset to get
	 * device off of PCI bus */
	iowrite32(selective_reset, &nic->csr->port);
	e100_write_flush(nic); udelay(20);

	/* Now fully reset device */
	iowrite32(software_reset, &nic->csr->port);
	e100_write_flush(nic); udelay(20);

	/* Mask off our interrupt line - it's unmasked after reset */
	e100_disable_irq(nic);
}

static int e100_self_test(struct nic *nic)
{
	u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest);

	/* Passing the self-test is a pretty good indication
	 * that the device can DMA to/from host memory */

	nic->mem->selftest.signature = 0;
	nic->mem->selftest.result = 0xFFFFFFFF;

	iowrite32(selftest | dma_addr, &nic->csr->port);
	e100_write_flush(nic);
	/* Wait 10 msec for self-test to complete */
	msleep(10);

	/* Interrupts are enabled after self-test */
	e100_disable_irq(nic);

	/* Check results of self-test */
	if (nic->mem->selftest.result != 0) {
		DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n",
			nic->mem->selftest.result);
		return -ETIMEDOUT;
	}
	if (nic->mem->selftest.signature == 0) {
		DPRINTK(HW, ERR, "Self-test failed: timed out\n");
		return -ETIMEDOUT;
	}

	return 0;
}

static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data)
{
	u32 cmd_addr_data[3];
	u8 ctrl;
	int i, j;

	/* Three cmds: write/erase enable, write data, write/erase disable */
	cmd_addr_data[0] = op_ewen << (addr_len - 2);
	cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) |
		le16_to_cpu(data);
	cmd_addr_data[2] = op_ewds << (addr_len - 2);

	/* Bit-bang cmds to write word to eeprom */
	for (j = 0; j < 3; j++) {

		/* Chip select */
		iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
		e100_write_flush(nic); udelay(4);

		for (i = 31; i >= 0; i--) {
			ctrl = (cmd_addr_data[j] & (1 << i)) ?
				eecs | eedi : eecs;
			iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
			e100_write_flush(nic); udelay(4);

			iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
			e100_write_flush(nic); udelay(4);
		}
		/* Wait 10 msec for cmd to complete */
		msleep(10);

		/* Chip deselect */
		iowrite8(0, &nic->csr->eeprom_ctrl_lo);
		e100_write_flush(nic); udelay(4);
	}
};

/* General technique stolen from the eepro100 driver - very clever */
static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
{
	u32 cmd_addr_data;
	u16 data = 0;
	u8 ctrl;
	int i;

	cmd_addr_data = ((op_read << *addr_len) | addr) << 16;

	/* Chip select */
	iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
	e100_write_flush(nic); udelay(4);

	/* Bit-bang to read word from eeprom */
	for (i = 31; i >= 0; i--) {
		ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
		iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
		e100_write_flush(nic); udelay(4);

		iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
		e100_write_flush(nic); udelay(4);

		/* Eeprom drives a dummy zero to EEDO after receiving
		 * complete address.  Use this to adjust addr_len. */
		ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
		if (!(ctrl & eedo) && i > 16) {
			*addr_len -= (i - 16);
			i = 17;
		}

		data = (data << 1) | (ctrl & eedo ? 1 : 0);
	}

	/* Chip deselect */
	iowrite8(0, &nic->csr->eeprom_ctrl_lo);
	e100_write_flush(nic); udelay(4);

	return cpu_to_le16(data);
};

/* Load entire EEPROM image into driver cache and validate checksum */
static int e100_eeprom_load(struct nic *nic)
{
	u16 addr, addr_len = 8, checksum = 0;

	/* Try reading with an 8-bit addr len to discover actual addr len */
	e100_eeprom_read(nic, &addr_len, 0);
	nic->eeprom_wc = 1 << addr_len;

	for (addr = 0; addr < nic->eeprom_wc; addr++) {
		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
		if (addr < nic->eeprom_wc - 1)
			checksum += le16_to_cpu(nic->eeprom[addr]);
	}

	/* The checksum, stored in the last word, is calculated such that
	 * the sum of words should be 0xBABA */
	if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) {
		DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
		if (!eeprom_bad_csum_allow)
			return -EAGAIN;
	}

	return 0;
}

/* Save (portion of) driver EEPROM cache to device and update checksum */
static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
{
	u16 addr, addr_len = 8, checksum = 0;

	/* Try reading with an 8-bit addr len to discover actual addr len */
	e100_eeprom_read(nic, &addr_len, 0);
	nic->eeprom_wc = 1 << addr_len;

	if (start + count >= nic->eeprom_wc)
		return -EINVAL;

	for (addr = start; addr < start + count; addr++)
		e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);

	/* The checksum, stored in the last word, is calculated such that
	 * the sum of words should be 0xBABA */
	for (addr = 0; addr < nic->eeprom_wc - 1; addr++)
		checksum += le16_to_cpu(nic->eeprom[addr]);
	nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
	e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
		nic->eeprom[nic->eeprom_wc - 1]);

	return 0;
}

#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
#define E100_WAIT_SCB_FAST 20       /* delay like the old code */
static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
	unsigned long flags;
	unsigned int i;
	int err = 0;

	spin_lock_irqsave(&nic->cmd_lock, flags);

	/* Previous command is accepted when SCB clears */
	for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
		if (likely(!ioread8(&nic->csr->scb.cmd_lo)))
			break;
		cpu_relax();
		if (unlikely(i > E100_WAIT_SCB_FAST))
			udelay(5);
	}
	if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
		err = -EAGAIN;
		goto err_unlock;
	}

	if (unlikely(cmd != cuc_resume))
		iowrite32(dma_addr, &nic->csr->scb.gen_ptr);
	iowrite8(cmd, &nic->csr->scb.cmd_lo);

err_unlock:
	spin_unlock_irqrestore(&nic->cmd_lock, flags);

	return err;
}

static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
{
	struct cb *cb;
	unsigned long flags;
	int err = 0;

	spin_lock_irqsave(&nic->cb_lock, flags);

	if (unlikely(!nic->cbs_avail)) {
		err = -ENOMEM;
		goto err_unlock;
	}

	cb = nic->cb_to_use;
	nic->cb_to_use = cb->next;
	nic->cbs_avail--;
	cb->skb = skb;

	if (unlikely(!nic->cbs_avail))
		err = -ENOSPC;

	cb_prepare(nic, cb, skb);

	/* Order is important otherwise we'll be in a race with h/w:
	 * set S-bit in current first, then clear S-bit in previous. */
	cb->command |= cpu_to_le16(cb_s);
	wmb();
	cb->prev->command &= cpu_to_le16(~cb_s);

	while (nic->cb_to_send != nic->cb_to_use) {
		if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
			nic->cb_to_send->dma_addr))) {
			/* Ok, here's where things get sticky.  It's
			 * possible that we can't schedule the command
			 * because the controller is too busy, so
			 * let's just queue the command and try again
			 * when another command is scheduled. */
			if (err == -ENOSPC) {
				//request a reset
				schedule_work(&nic->tx_timeout_task);
			}
			break;
		} else {
			nic->cuc_cmd = cuc_resume;
			nic->cb_to_send = nic->cb_to_send->next;
		}
	}

err_unlock:
	spin_unlock_irqrestore(&nic->cb_lock, flags);

	return err;
}

static int mdio_read(struct net_device *netdev, int addr, int reg)
{
	struct nic *nic = netdev_priv(netdev);
	return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0);
}

static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
{
	struct nic *nic = netdev_priv(netdev);

	nic->mdio_ctrl(nic, addr, mdi_write, reg, data);
}

/* the standard mdio_ctrl() function for usual MII-compliant hardware */
static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
{
	u32 data_out = 0;
	unsigned int i;
	unsigned long flags;


	/*
	 * Stratus87247: we shouldn't be writing the MDI control
	 * register until the Ready bit shows True.  Also, since
	 * manipulation of the MDI control registers is a multi-step
	 * procedure it should be done under lock.
	 */
	spin_lock_irqsave(&nic->mdio_lock, flags);
	for (i = 100; i; --i) {
		if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready)
			break;
		udelay(20);
	}
	if (unlikely(!i)) {
		printk("e100.mdio_ctrl(%s) won't go Ready\n",
			nic->netdev->name );
		spin_unlock_irqrestore(&nic->mdio_lock, flags);
		return 0;		/* No way to indicate timeout error */
	}
	iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);

	for (i = 0; i < 100; i++) {
		udelay(20);
		if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready)
			break;
	}
	spin_unlock_irqrestore(&nic->mdio_lock, flags);
	DPRINTK(HW, DEBUG,
		"%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
		dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out);
	return (u16)data_out;
}

/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */
static u16 mdio_ctrl_phy_82552_v(struct nic *nic,
				 u32 addr,
				 u32 dir,
				 u32 reg,
				 u16 data)
{
	if ((reg == MII_BMCR) && (dir == mdi_write)) {
		if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) {
			u16 advert = mdio_read(nic->netdev, nic->mii.phy_id,
							MII_ADVERTISE);

			/*
			 * Workaround Si issue where sometimes the part will not
			 * autoneg to 100Mbps even when advertised.
			 */
			if (advert & ADVERTISE_100FULL)
				data |= BMCR_SPEED100 | BMCR_FULLDPLX;
			else if (advert & ADVERTISE_100HALF)
				data |= BMCR_SPEED100;
		}
	}
	return mdio_ctrl_hw(nic, addr, dir, reg, data);
}

/* Fully software-emulated mdio_ctrl() function for cards without
 * MII-compliant PHYs.
 * For now, this is mainly geared towards 80c24 support; in case of further
 * requirements for other types (i82503, ...?) either extend this mechanism
 * or split it, whichever is cleaner.
 */
static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic,
				      u32 addr,
				      u32 dir,
				      u32 reg,
				      u16 data)
{
	/* might need to allocate a netdev_priv'ed register array eventually
	 * to be able to record state changes, but for now
	 * some fully hardcoded register handling ought to be ok I guess. */

	if (dir == mdi_read) {
		switch (reg) {
		case MII_BMCR:
			/* Auto-negotiation, right? */
			return  BMCR_ANENABLE |
				BMCR_FULLDPLX;
		case MII_BMSR:
			return	BMSR_LSTATUS /* for mii_link_ok() */ |
				BMSR_ANEGCAPABLE |
				BMSR_10FULL;
		case MII_ADVERTISE:
			/* 80c24 is a "combo card" PHY, right? */
			return	ADVERTISE_10HALF |
				ADVERTISE_10FULL;
		default:
			DPRINTK(HW, DEBUG,
		"%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
		dir == mdi_read ? "READ" : "WRITE", addr, reg, data);
			return 0xFFFF;
		}
	} else {
		switch (reg) {
		default:
			DPRINTK(HW, DEBUG,
		"%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
		dir == mdi_read ? "READ" : "WRITE", addr, reg, data);
			return 0xFFFF;
		}
	}
}
static inline int e100_phy_supports_mii(struct nic *nic)
{
	/* for now, just check it by comparing whether we
	   are using MII software emulation.
	*/
	return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated);
}

static void e100_get_defaults(struct nic *nic)
{
	struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
	struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };

	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
	if (nic->mac == mac_unknown)
		nic->mac = mac_82557_D100_A;

	nic->params.rfds = rfds;
	nic->params.cbs = cbs;

	/* Quadwords to DMA into FIFO before starting frame transmit */
	nic->tx_threshold = 0xE0;

	/* no interrupt for every tx completion, delay = 256us if not 557 */
	nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
		((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));

	/* Template for a freshly allocated RFD */
	nic->blank_rfd.command = 0;
	nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF);
	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);

	/* MII setup */
	nic->mii.phy_id_mask = 0x1F;
	nic->mii.reg_num_mask = 0x1F;
	nic->mii.dev = nic->netdev;
	nic->mii.mdio_read = mdio_read;
	nic->mii.mdio_write = mdio_write;
}

static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
	struct config *config = &cb->u.config;
	u8 *c = (u8 *)config;

	cb->command = cpu_to_le16(cb_config);

	memset(config, 0, sizeof(struct config));

	config->byte_count = 0x16;		/* bytes in this struct */
	config->rx_fifo_limit = 0x8;		/* bytes in FIFO before DMA */
	config->direct_rx_dma = 0x1;		/* reserved */
	config->standard_tcb = 0x1;		/* 1=standard, 0=extended */
	config->standard_stat_counter = 0x1;	/* 1=standard, 0=extended */
	config->rx_discard_short_frames = 0x1;	/* 1=discard, 0=pass */
	config->tx_underrun_retry = 0x3;	/* # of underrun retries */
	if (e100_phy_supports_mii(nic))
		config->mii_mode = 1;           /* 1=MII mode, 0=i82503 mode */
	config->pad10 = 0x6;
	config->no_source_addr_insertion = 0x1;	/* 1=no, 0=yes */
	config->preamble_length = 0x2;		/* 0=1, 1=3, 2=7, 3=15 bytes */
	config->ifs = 0x6;			/* x16 = inter frame spacing */
	config->ip_addr_hi = 0xF2;		/* ARP IP filter - not used */
	config->pad15_1 = 0x1;
	config->pad15_2 = 0x1;
	config->crs_or_cdt = 0x0;		/* 0=CRS only, 1=CRS or CDT */
	config->fc_delay_hi = 0x40;		/* time delay for fc frame */
	config->tx_padding = 0x1;		/* 1=pad short frames */
	config->fc_priority_threshold = 0x7;	/* 7=priority fc disabled */
	config->pad18 = 0x1;
	config->full_duplex_pin = 0x1;		/* 1=examine FDX# pin */
	config->pad20_1 = 0x1F;
	config->fc_priority_location = 0x1;	/* 1=byte#31, 0=byte#19 */
	config->pad21_1 = 0x5;

	config->adaptive_ifs = nic->adaptive_ifs;
	config->loopback = nic->loopback;

	if (nic->mii.force_media && nic->mii.full_duplex)
		config->full_duplex_force = 0x1;	/* 1=force, 0=auto */

	if (nic->flags & promiscuous || nic->loopback) {
		config->rx_save_bad_frames = 0x1;	/* 1=save, 0=discard */
		config->rx_discard_short_frames = 0x0;	/* 1=discard, 0=save */
		config->promiscuous_mode = 0x1;		/* 1=on, 0=off */
	}

	if (nic->flags & multicast_all)
		config->multicast_all = 0x1;		/* 1=accept, 0=no */

	/* disable WoL when up */
	if (netif_running(nic->netdev) || !(nic->flags & wol_magic))
		config->magic_packet_disable = 0x1;	/* 1=off, 0=on */

	if (nic->mac >= mac_82558_D101_A4) {
		config->fc_disable = 0x1;	/* 1=Tx fc off, 0=Tx fc on */
		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
		if (nic->mac >= mac_82559_D101M) {
			config->tno_intr = 0x1;		/* TCO stats enable */
			/* Enable TCO in extended config */
			if (nic->mac >= mac_82551_10) {
				config->byte_count = 0x20; /* extended bytes */
				config->rx_d102_mode = 0x1; /* GMRC for TCO */
			}
		} else {
			config->standard_stat_counter = 0x0;
		}
	}

	DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
		c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
	DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
		c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
	DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
}

/*************************************************************************
*  CPUSaver parameters
*
*  All CPUSaver parameters are 16-bit literals that are part of a
*  "move immediate value" instruction.  By changing the value of
*  the literal in the instruction before the code is loaded, the
*  driver can change the algorithm.
*
*  INTDELAY - This loads the dead-man timer with its initial value.
*    When this timer expires the interrupt is asserted, and the
*    timer is reset each time a new packet is received.  (see
*    BUNDLEMAX below to set the limit on number of chained packets)
*    The current default is 0x600 or 1536.  Experiments show that
*    the value should probably stay within the 0x200 - 0x1000.
*
*  BUNDLEMAX -
*    This sets the maximum number of frames that will be bundled.  In
*    some situations, such as the TCP windowing algorithm, it may be
*    better to limit the growth of the bundle size than let it go as
*    high as it can, because that could cause too much added latency.
*    The default is six, because this is the number of packets in the
*    default TCP window size.  A value of 1 would make CPUSaver indicate
*    an interrupt for every frame received.  If you do not want to put
*    a limit on the bundle size, set this value to xFFFF.
*
*  BUNDLESMALL -
*    This contains a bit-mask describing the minimum size frame that
*    will be bundled.  The default masks the lower 7 bits, which means
*    that any frame less than 128 bytes in length will not be bundled,
*    but will instead immediately generate an interrupt.  This does
*    not affect the current bundle in any way.  Any frame that is 128
*    bytes or large will be bundled normally.  This feature is meant
*    to provide immediate indication of ACK frames in a TCP environment.
*    Customers were seeing poor performance when a machine with CPUSaver
*    enabled was sending but not receiving.  The delay introduced when
*    the ACKs were received was enough to reduce total throughput, because
*    the sender would sit idle until the ACK was finally seen.
*
*    The current default is 0xFF80, which masks out the lower 7 bits.
*    This means that any frame which is x7F (127) bytes or smaller
*    will cause an immediate interrupt.  Because this value must be a
*    bit mask, there are only a few valid values that can be used.  To
*    turn this feature off, the driver can write the value xFFFF to the
*    lower word of this instruction (in the same way that the other
*    parameters are used).  Likewise, a value of 0xF800 (2047) would
*    cause an interrupt to be generated for every frame, because all
*    standard Ethernet frames are <= 2047 bytes in length.
*************************************************************************/

/* if you wish to disable the ucode functionality, while maintaining the
 * workarounds it provides, set the following defines to:
 * BUNDLESMALL 0
 * BUNDLEMAX 1
 * INTDELAY 1
 */
#define BUNDLESMALL 1
#define BUNDLEMAX (u16)6
#define INTDELAY (u16)1536 /* 0x600 */

/* Initialize firmware */
static const struct firmware *e100_request_firmware(struct nic *nic)
{
	const char *fw_name;
	const struct firmware *fw;
	u8 timer, bundle, min_size;
	int err;

	/* do not load u-code for ICH devices */
	if (nic->flags & ich)
		return NULL;

	/* Search for ucode match against h/w revision */
	if (nic->mac == mac_82559_D101M)
		fw_name = FIRMWARE_D101M;
	else if (nic->mac == mac_82559_D101S)
		fw_name = FIRMWARE_D101S;
	else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10)
		fw_name = FIRMWARE_D102E;
	else /* No ucode on other devices */
		return NULL;

	err = request_firmware(&fw, fw_name, &nic->pdev->dev);
	if (err) {
		DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n",
			fw_name, err);
		return ERR_PTR(err);
	}
	/* Firmware should be precisely UCODE_SIZE (words) plus three bytes
	   indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */
	if (fw->size != UCODE_SIZE * 4 + 3) {
		DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n",
			fw_name, fw->size);
		release_firmware(fw);
		return ERR_PTR(-EINVAL);
	}

	/* Read timer, bundle and min_size from end of firmware blob */
	timer = fw->data[UCODE_SIZE * 4];
	bundle = fw->data[UCODE_SIZE * 4 + 1];
	min_size = fw->data[UCODE_SIZE * 4 + 2];

	if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE ||
	    min_size >= UCODE_SIZE) {
		DPRINTK(PROBE, ERR,
			"\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n",
			fw_name, timer, bundle, min_size);
		release_firmware(fw);
		return ERR_PTR(-EINVAL);
	}
	/* OK, firmware is validated and ready to use... */
	return fw;
}

static void e100_setup_ucode(struct nic *nic, struct cb *cb,
			     struct sk_buff *skb)
{
	const struct firmware *fw = (void *)skb;
	u8 timer, bundle, min_size;

	/* It's not a real skb; we just abused the fact that e100_exec_cb
	   will pass it through to here... */
	cb->skb = NULL;

	/* firmware is stored as little endian already */
	memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4);

	/* Read timer, bundle and min_size from end of firmware blob */
	timer = fw->data[UCODE_SIZE * 4];
	bundle = fw->data[UCODE_SIZE * 4 + 1];
	min_size = fw->data[UCODE_SIZE * 4 + 2];

	/* Insert user-tunable settings in cb->u.ucode */
	cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000);
	cb->u.ucode[timer] |= cpu_to_le32(INTDELAY);
	cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000);
	cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX);
	cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000);
	cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);

	cb->command = cpu_to_le16(cb_ucode | cb_el);
}

static inline int e100_load_ucode_wait(struct nic *nic)
{
	const struct firmware *fw;
	int err = 0, counter = 50;
	struct cb *cb = nic->cb_to_clean;

	fw = e100_request_firmware(nic);
	/* If it's NULL, then no ucode is required */
	if (!fw || IS_ERR(fw))
		return PTR_ERR(fw);

	if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
		DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);

	/* must restart cuc */
	nic->cuc_cmd = cuc_start;

	/* wait for completion */
	e100_write_flush(nic);
	udelay(10);

	/* wait for possibly (ouch) 500ms */
	while (!(cb->status & cpu_to_le16(cb_complete))) {
		msleep(10);
		if (!--counter) break;
	}

	/* ack any interrupts, something could have been set */
	iowrite8(~0, &nic->csr->scb.stat_ack);

	/* if the command failed, or is not OK, notify and return */
	if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
		DPRINTK(PROBE,ERR, "ucode load failed\n");
		err = -EPERM;
	}

	return err;
}

static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
	struct sk_buff *skb)
{
	cb->command = cpu_to_le16(cb_iaaddr);
	memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
}

static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
	cb->command = cpu_to_le16(cb_dump);
	cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
		offsetof(struct mem, dump_buf));
}

static int e100_phy_check_without_mii(struct nic *nic)
{
	u8 phy_type;
	int without_mii;

	phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f;

	switch (phy_type) {
	case NoSuchPhy: /* Non-MII PHY; UNTESTED! */
	case I82503: /* Non-MII PHY; UNTESTED! */
	case S80C24: /* Non-MII PHY; tested and working */
		/* paragraph from the FreeBSD driver, "FXP_PHY_80C24":
		 * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter
		 * doesn't have a programming interface of any sort.  The
		 * media is sensed automatically based on how the link partner
		 * is configured.  This is, in essence, manual configuration.
		 */
		DPRINTK(PROBE, INFO,
			 "found MII-less i82503 or 80c24 or other PHY\n");

		nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated;
		nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */

		/* these might be needed for certain MII-less cards...
		 * nic->flags |= ich;
		 * nic->flags |= ich_10h_workaround; */

		without_mii = 1;
		break;
	default:
		without_mii = 0;
		break;
	}
	return without_mii;
}

#define NCONFIG_AUTO_SWITCH	0x0080
#define MII_NSC_CONG		MII_RESV1
#define NSC_CONG_ENABLE		0x0100
#define NSC_CONG_TXREADY	0x0400
#define ADVERTISE_FC_SUPPORTED	0x0400
static int e100_phy_init(struct nic *nic)
{
	struct net_device *netdev = nic->netdev;
	u32 addr;
	u16 bmcr, stat, id_lo, id_hi, cong;

	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
	for (addr = 0; addr < 32; addr++) {
		nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
		if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
			break;
	}
	if (addr == 32) {
		/* uhoh, no PHY detected: check whether we seem to be some
		 * weird, rare variant which is *known* to not have any MII.
		 * But do this AFTER MII checking only, since this does
		 * lookup of EEPROM values which may easily be unreliable. */
		if (e100_phy_check_without_mii(nic))
			return 0; /* simply return and hope for the best */
		else {
			/* for unknown cases log a fatal error */
			DPRINTK(HW, ERR,
				"Failed to locate any known PHY, aborting.\n");
			return -EAGAIN;
		}
	} else
		DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);

	/* Isolate all the PHY ids */
	for (addr = 0; addr < 32; addr++)
		mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
	/* Select the discovered PHY */
	bmcr &= ~BMCR_ISOLATE;
	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);

	/* Get phy ID */
	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
	DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);

	/* Handle National tx phys */
#define NCS_PHY_MODEL_MASK	0xFFF0FFFF
	if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
		/* Disable congestion control */
		cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
		cong |= NSC_CONG_TXREADY;
		cong &= ~NSC_CONG_ENABLE;
		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
	}

	if (nic->phy == phy_82552_v) {
		u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);

		/* assign special tweaked mdio_ctrl() function */
		nic->mdio_ctrl = mdio_ctrl_phy_82552_v;

		/* Workaround Si not advertising flow-control during autoneg */
		advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
		mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);

		/* Reset for the above changes to take effect */
		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
		bmcr |= BMCR_RESET;
		mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
	} else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
		!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
		/* enable/disable MDI/MDI-X auto-switching. */
		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
				nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
	}

	return 0;
}

static int e100_hw_init(struct nic *nic)
{
	int err;

	e100_hw_reset(nic);

	DPRINTK(HW, ERR, "e100_hw_init\n");
	if (!in_interrupt() && (err = e100_self_test(nic)))
		return err;

	if ((err = e100_phy_init(nic)))
		return err;
	if ((err = e100_exec_cmd(nic, cuc_load_base, 0)))
		return err;
	if ((err = e100_exec_cmd(nic, ruc_load_base, 0)))
		return err;
	if ((err = e100_load_ucode_wait(nic)))
		return err;
	if ((err = e100_exec_cb(nic, NULL, e100_configure)))
		return err;
	if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
		return err;
	if ((err = e100_exec_cmd(nic, cuc_dump_addr,
		nic->dma_addr + offsetof(struct mem, stats))))
		return err;
	if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
		return err;

	e100_disable_irq(nic);

	return 0;
}

static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
	struct net_device *netdev = nic->netdev;
	struct dev_mc_list *list = netdev->mc_list;
	u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS);

	cb->command = cpu_to_le16(cb_multi);
	cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
	for (i = 0; list && i < count; i++, list = list->next)
		memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr,
			ETH_ALEN);
}

static void e100_set_multicast_list(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);

	DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n",
		netdev->mc_count, netdev->flags);

	if (netdev->flags & IFF_PROMISC)
		nic->flags |= promiscuous;
	else
		nic->flags &= ~promiscuous;

	if (netdev->flags & IFF_ALLMULTI ||
		netdev->mc_count > E100_MAX_MULTICAST_ADDRS)
		nic->flags |= multicast_all;
	else
		nic->flags &= ~multicast_all;

	e100_exec_cb(nic, NULL, e100_configure);
	e100_exec_cb(nic, NULL, e100_multi);
}

static void e100_update_stats(struct nic *nic)
{
	struct net_device *dev = nic->netdev;
	struct net_device_stats *ns = &dev->stats;
	struct stats *s = &nic->mem->stats;
	__le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
		(nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames :
		&s->complete;

	/* Device's stats reporting may take several microseconds to
	 * complete, so we're always waiting for results of the
	 * previous command. */

	if (*complete == cpu_to_le32(cuc_dump_reset_complete)) {
		*complete = 0;
		nic->tx_frames = le32_to_cpu(s->tx_good_frames);
		nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
		ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions);
		ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions);
		ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs);
		ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns);
		ns->collisions += nic->tx_collisions;
		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
			le32_to_cpu(s->tx_lost_crs);
		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
			nic->rx_over_length_errors;
		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
		ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
		ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
			le32_to_cpu(s->rx_alignment_errors) +
			le32_to_cpu(s->rx_short_frame_errors) +
			le32_to_cpu(s->rx_cdt_errors);
		nic->tx_deferred += le32_to_cpu(s->tx_deferred);
		nic->tx_single_collisions +=
			le32_to_cpu(s->tx_single_collisions);
		nic->tx_multiple_collisions +=
			le32_to_cpu(s->tx_multiple_collisions);
		if (nic->mac >= mac_82558_D101_A4) {
			nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
			nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
			nic->rx_fc_unsupported +=
				le32_to_cpu(s->fc_rcv_unsupported);
			if (nic->mac >= mac_82559_D101M) {
				nic->tx_tco_frames +=
					le16_to_cpu(s->xmt_tco_frames);
				nic->rx_tco_frames +=
					le16_to_cpu(s->rcv_tco_frames);
			}
		}
	}


	if (e100_exec_cmd(nic, cuc_dump_reset, 0))
		DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}

static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
{
	/* Adjust inter-frame-spacing (IFS) between two transmits if
	 * we're getting collisions on a half-duplex connection. */

	if (duplex == DUPLEX_HALF) {
		u32 prev = nic->adaptive_ifs;
		u32 min_frames = (speed == SPEED_100) ? 1000 : 100;

		if ((nic->tx_frames / 32 < nic->tx_collisions) &&
		   (nic->tx_frames > min_frames)) {
			if (nic->adaptive_ifs < 60)
				nic->adaptive_ifs += 5;
		} else if (nic->tx_frames < min_frames) {
			if (nic->adaptive_ifs >= 5)
				nic->adaptive_ifs -= 5;
		}
		if (nic->adaptive_ifs != prev)
			e100_exec_cb(nic, NULL, e100_configure);
	}
}

static void e100_watchdog(unsigned long data)
{
	struct nic *nic = (struct nic *)data;
	struct ethtool_cmd cmd;

	DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies);

	/* mii library handles link maintenance tasks */

	mii_ethtool_gset(&nic->mii, &cmd);

	if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
		printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n",
		       nic->netdev->name,
		       cmd.speed == SPEED_100 ? "100" : "10",
		       cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
	} else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
		printk(KERN_INFO "e100: %s NIC Link is Down\n",
		       nic->netdev->name);
	}

	mii_check_link(&nic->mii);

	/* Software generated interrupt to recover from (rare) Rx
	 * allocation failure.
	 * Unfortunately have to use a spinlock to not re-enable interrupts
	 * accidentally, due to hardware that shares a register between the
	 * interrupt mask bit and the SW Interrupt generation bit */
	spin_lock_irq(&nic->cmd_lock);
	iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
	e100_write_flush(nic);
	spin_unlock_irq(&nic->cmd_lock);

	e100_update_stats(nic);
	e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);

	if (nic->mac <= mac_82557_D100_C)
		/* Issue a multicast command to workaround a 557 lock up */
		e100_set_multicast_list(nic->netdev);

	if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF)
		/* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */
		nic->flags |= ich_10h_workaround;
	else
		nic->flags &= ~ich_10h_workaround;

	mod_timer(&nic->watchdog,
		  round_jiffies(jiffies + E100_WATCHDOG_PERIOD));
}

static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
	struct sk_buff *skb)
{
	cb->command = nic->tx_command;
	/* interrupt every 16 packets regardless of delay */
	if ((nic->cbs_avail & ~15) == nic->cbs_avail)
		cb->command |= cpu_to_le16(cb_i);
	cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
	cb->u.tcb.tcb_byte_count = 0;
	cb->u.tcb.threshold = nic->tx_threshold;
	cb->u.tcb.tbd_count = 1;
	cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
		skb->data, skb->len, PCI_DMA_TODEVICE));
	/* check for mapping failure? */
	cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
}

static netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
				   struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	int err;

	if (nic->flags & ich_10h_workaround) {
		/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
		   Issue a NOP command followed by a 1us delay before
		   issuing the Tx command. */
		if (e100_exec_cmd(nic, cuc_nop, 0))
			DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n");
		udelay(1);
	}

	err = e100_exec_cb(nic, skb, e100_xmit_prepare);

	switch (err) {
	case -ENOSPC:
		/* We queued the skb, but now we're out of space. */
		DPRINTK(TX_ERR, DEBUG, "No space for CB\n");
		netif_stop_queue(netdev);
		break;
	case -ENOMEM:
		/* This is a hard error - log it. */
		DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n");
		netif_stop_queue(netdev);
		return NETDEV_TX_BUSY;
	}

	netdev->trans_start = jiffies;
	return NETDEV_TX_OK;
}

static int e100_tx_clean(struct nic *nic)
{
	struct net_device *dev = nic->netdev;
	struct cb *cb;
	int tx_cleaned = 0;

	spin_lock(&nic->cb_lock);

	/* Clean CBs marked complete */
	for (cb = nic->cb_to_clean;
	    cb->status & cpu_to_le16(cb_complete);
	    cb = nic->cb_to_clean = cb->next) {
		DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n",
		        (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)),
		        cb->status);

		if (likely(cb->skb != NULL)) {
			dev->stats.tx_packets++;
			dev->stats.tx_bytes += cb->skb->len;

			pci_unmap_single(nic->pdev,
				le32_to_cpu(cb->u.tcb.tbd.buf_addr),
				le16_to_cpu(cb->u.tcb.tbd.size),
				PCI_DMA_TODEVICE);
			dev_kfree_skb_any(cb->skb);
			cb->skb = NULL;
			tx_cleaned = 1;
		}
		cb->status = 0;
		nic->cbs_avail++;
	}

	spin_unlock(&nic->cb_lock);

	/* Recover from running out of Tx resources in xmit_frame */
	if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
		netif_wake_queue(nic->netdev);

	return tx_cleaned;
}

static void e100_clean_cbs(struct nic *nic)
{
	if (nic->cbs) {
		while (nic->cbs_avail != nic->params.cbs.count) {
			struct cb *cb = nic->cb_to_clean;
			if (cb->skb) {
				pci_unmap_single(nic->pdev,
					le32_to_cpu(cb->u.tcb.tbd.buf_addr),
					le16_to_cpu(cb->u.tcb.tbd.size),
					PCI_DMA_TODEVICE);
				dev_kfree_skb(cb->skb);
			}
			nic->cb_to_clean = nic->cb_to_clean->next;
			nic->cbs_avail++;
		}
		pci_free_consistent(nic->pdev,
			sizeof(struct cb) * nic->params.cbs.count,
			nic->cbs, nic->cbs_dma_addr);
		nic->cbs = NULL;
		nic->cbs_avail = 0;
	}
	nic->cuc_cmd = cuc_start;
	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean =
		nic->cbs;
}

static int e100_alloc_cbs(struct nic *nic)
{
	struct cb *cb;
	unsigned int i, count = nic->params.cbs.count;

	nic->cuc_cmd = cuc_start;
	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;
	nic->cbs_avail = 0;

	nic->cbs = pci_alloc_consistent(nic->pdev,
		sizeof(struct cb) * count, &nic->cbs_dma_addr);
	if (!nic->cbs)
		return -ENOMEM;

	for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
		cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
		cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;

		cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
		cb->link = cpu_to_le32(nic->cbs_dma_addr +
			((i+1) % count) * sizeof(struct cb));
		cb->skb = NULL;
	}

	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
	nic->cbs_avail = count;

	return 0;
}

static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
{
	if (!nic->rxs) return;
	if (RU_SUSPENDED != nic->ru_running) return;

	/* handle init time starts */
	if (!rx) rx = nic->rxs;

	/* (Re)start RU if suspended or idle and RFA is non-NULL */
	if (rx->skb) {
		e100_exec_cmd(nic, ruc_start, rx->dma_addr);
		nic->ru_running = RU_RUNNING;
	}
}

#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
{
	if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN)))
		return -ENOMEM;

	/* Align, init, and map the RFD. */
	skb_reserve(rx->skb, NET_IP_ALIGN);
	skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd));
	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);

	if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) {
		dev_kfree_skb_any(rx->skb);
		rx->skb = NULL;
		rx->dma_addr = 0;
		return -ENOMEM;
	}

	/* Link the RFD to end of RFA by linking previous RFD to
	 * this one.  We are safe to touch the previous RFD because
	 * it is protected by the before last buffer's el bit being set */
	if (rx->prev->skb) {
		struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
		put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
		pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
			sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
	}

	return 0;
}

static int e100_rx_indicate(struct nic *nic, struct rx *rx,
	unsigned int *work_done, unsigned int work_to_do)
{
	struct net_device *dev = nic->netdev;
	struct sk_buff *skb = rx->skb;
	struct rfd *rfd = (struct rfd *)skb->data;
	u16 rfd_status, actual_size;

	if (unlikely(work_done && *work_done >= work_to_do))
		return -EAGAIN;

	/* Need to sync before taking a peek at cb_complete bit */
	pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr,
		sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
	rfd_status = le16_to_cpu(rfd->status);

	DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);

	/* If data isn't ready, nothing to indicate */
	if (unlikely(!(rfd_status & cb_complete))) {
		/* If the next buffer has the el bit, but we think the receiver
		 * is still running, check to see if it really stopped while
		 * we had interrupts off.
		 * This allows for a fast restart without re-enabling
		 * interrupts */
		if ((le16_to_cpu(rfd->command) & cb_el) &&
		    (RU_RUNNING == nic->ru_running))

			if (ioread8(&nic->csr->scb.status) & rus_no_res)
				nic->ru_running = RU_SUSPENDED;
		pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
					       sizeof(struct rfd),
					       PCI_DMA_FROMDEVICE);
		return -ENODATA;
	}

	/* Get actual data size */
	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
	if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
		actual_size = RFD_BUF_LEN - sizeof(struct rfd);

	/* Get data */
	pci_unmap_single(nic->pdev, rx->dma_addr,
		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);

	/* If this buffer has the el bit, but we think the receiver
	 * is still running, check to see if it really stopped while
	 * we had interrupts off.
	 * This allows for a fast restart without re-enabling interrupts.
	 * This can happen when the RU sees the size change but also sees
	 * the el bit set. */
	if ((le16_to_cpu(rfd->command) & cb_el) &&
	    (RU_RUNNING == nic->ru_running)) {

	    if (ioread8(&nic->csr->scb.status) & rus_no_res)
		nic->ru_running = RU_SUSPENDED;
	}

	/* Pull off the RFD and put the actual data (minus eth hdr) */
	skb_reserve(skb, sizeof(struct rfd));
	skb_put(skb, actual_size);
	skb->protocol = eth_type_trans(skb, nic->netdev);

	if (unlikely(!(rfd_status & cb_ok))) {
		/* Don't indicate if hardware indicates errors */
		dev_kfree_skb_any(skb);
	} else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
		/* Don't indicate oversized frames */
		nic->rx_over_length_errors++;
		dev_kfree_skb_any(skb);
	} else {
		dev->stats.rx_packets++;
		dev->stats.rx_bytes += actual_size;
		netif_receive_skb(skb);
		if (work_done)
			(*work_done)++;
	}

	rx->skb = NULL;

	return 0;
}

static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
	unsigned int work_to_do)
{
	struct rx *rx;
	int restart_required = 0, err = 0;
	struct rx *old_before_last_rx, *new_before_last_rx;
	struct rfd *old_before_last_rfd, *new_before_last_rfd;

	/* Indicate newly arrived packets */
	for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
		err = e100_rx_indicate(nic, rx, work_done, work_to_do);
		/* Hit quota or no more to clean */
		if (-EAGAIN == err || -ENODATA == err)
			break;
	}


	/* On EAGAIN, hit quota so have more work to do, restart once
	 * cleanup is complete.
	 * Else, are we already rnr? then pay attention!!! this ensures that
	 * the state machine progression never allows a start with a
	 * partially cleaned list, avoiding a race between hardware
	 * and rx_to_clean when in NAPI mode */
	if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running)
		restart_required = 1;

	old_before_last_rx = nic->rx_to_use->prev->prev;
	old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;

	/* Alloc new skbs to refill list */
	for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
		if (unlikely(e100_rx_alloc_skb(nic, rx)))
			break; /* Better luck next time (see watchdog) */
	}

	new_before_last_rx = nic->rx_to_use->prev->prev;
	if (new_before_last_rx != old_before_last_rx) {
		/* Set the el-bit on the buffer that is before the last buffer.
		 * This lets us update the next pointer on the last buffer
		 * without worrying about hardware touching it.
		 * We set the size to 0 to prevent hardware from touching this
		 * buffer.
		 * When the hardware hits the before last buffer with el-bit
		 * and size of 0, it will RNR interrupt, the RUS will go into
		 * the No Resources state.  It will not complete nor write to
		 * this buffer. */
		new_before_last_rfd =
			(struct rfd *)new_before_last_rx->skb->data;
		new_before_last_rfd->size = 0;
		new_before_last_rfd->command |= cpu_to_le16(cb_el);
		pci_dma_sync_single_for_device(nic->pdev,
			new_before_last_rx->dma_addr, sizeof(struct rfd),
			PCI_DMA_BIDIRECTIONAL);

		/* Now that we have a new stopping point, we can clear the old
		 * stopping point.  We must sync twice to get the proper
		 * ordering on the hardware side of things. */
		old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
		pci_dma_sync_single_for_device(nic->pdev,
			old_before_last_rx->dma_addr, sizeof(struct rfd),
			PCI_DMA_BIDIRECTIONAL);
		old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
		pci_dma_sync_single_for_device(nic->pdev,
			old_before_last_rx->dma_addr, sizeof(struct rfd),
			PCI_DMA_BIDIRECTIONAL);
	}

	if (restart_required) {
		// ack the rnr?
		iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
		e100_start_receiver(nic, nic->rx_to_clean);
		if (work_done)
			(*work_done)++;
	}
}

static void e100_rx_clean_list(struct nic *nic)
{
	struct rx *rx;
	unsigned int i, count = nic->params.rfds.count;

	nic->ru_running = RU_UNINITIALIZED;

	if (nic->rxs) {
		for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
			if (rx->skb) {
				pci_unmap_single(nic->pdev, rx->dma_addr,
					RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
				dev_kfree_skb(rx->skb);
			}
		}
		kfree(nic->rxs);
		nic->rxs = NULL;
	}

	nic->rx_to_use = nic->rx_to_clean = NULL;
}

static int e100_rx_alloc_list(struct nic *nic)
{
	struct rx *rx;
	unsigned int i, count = nic->params.rfds.count;
	struct rfd *before_last;

	nic->rx_to_use = nic->rx_to_clean = NULL;
	nic->ru_running = RU_UNINITIALIZED;

	if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
		return -ENOMEM;

	for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
		rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
		rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
		if (e100_rx_alloc_skb(nic, rx)) {
			e100_rx_clean_list(nic);
			return -ENOMEM;
		}
	}
	/* Set the el-bit on the buffer that is before the last buffer.
	 * This lets us update the next pointer on the last buffer without
	 * worrying about hardware touching it.
	 * We set the size to 0 to prevent hardware from touching this buffer.
	 * When the hardware hits the before last buffer with el-bit and size
	 * of 0, it will RNR interrupt, the RU will go into the No Resources
	 * state.  It will not complete nor write to this buffer. */
	rx = nic->rxs->prev->prev;
	before_last = (struct rfd *)rx->skb->data;
	before_last->command |= cpu_to_le16(cb_el);
	before_last->size = 0;
	pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
		sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);

	nic->rx_to_use = nic->rx_to_clean = nic->rxs;
	nic->ru_running = RU_SUSPENDED;

	return 0;
}

static irqreturn_t e100_intr(int irq, void *dev_id)
{
	struct net_device *netdev = dev_id;
	struct nic *nic = netdev_priv(netdev);
	u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);

	DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);

	if (stat_ack == stat_ack_not_ours ||	/* Not our interrupt */
	   stat_ack == stat_ack_not_present)	/* Hardware is ejected */
		return IRQ_NONE;

	/* Ack interrupt(s) */
	iowrite8(stat_ack, &nic->csr->scb.stat_ack);

	/* We hit Receive No Resource (RNR); restart RU after cleaning */
	if (stat_ack & stat_ack_rnr)
		nic->ru_running = RU_SUSPENDED;

	if (likely(napi_schedule_prep(&nic->napi))) {
		e100_disable_irq(nic);
		__napi_schedule(&nic->napi);
	}

	return IRQ_HANDLED;
}

static int e100_poll(struct napi_struct *napi, int budget)
{
	struct nic *nic = container_of(napi, struct nic, napi);
	unsigned int work_done = 0;

	e100_rx_clean(nic, &work_done, budget);
	e100_tx_clean(nic);

	/* If budget not fully consumed, exit the polling mode */
	if (work_done < budget) {
		napi_complete(napi);
		e100_enable_irq(nic);
	}

	return work_done;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void e100_netpoll(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);

	e100_disable_irq(nic);
	e100_intr(nic->pdev->irq, netdev);
	e100_tx_clean(nic);
	e100_enable_irq(nic);
}
#endif

static int e100_set_mac_address(struct net_device *netdev, void *p)
{
	struct nic *nic = netdev_priv(netdev);
	struct sockaddr *addr = p;

	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	e100_exec_cb(nic, NULL, e100_setup_iaaddr);

	return 0;
}

static int e100_change_mtu(struct net_device *netdev, int new_mtu)
{
	if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
		return -EINVAL;
	netdev->mtu = new_mtu;
	return 0;
}

static int e100_asf(struct nic *nic)
{
	/* ASF can be enabled from eeprom */
	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
}

static int e100_up(struct nic *nic)
{
	int err;

	if ((err = e100_rx_alloc_list(nic)))
		return err;
	if ((err = e100_alloc_cbs(nic)))
		goto err_rx_clean_list;
	if ((err = e100_hw_init(nic)))
		goto err_clean_cbs;
	e100_set_multicast_list(nic->netdev);
	e100_start_receiver(nic, NULL);
	mod_timer(&nic->watchdog, jiffies);
	if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
		nic->netdev->name, nic->netdev)))
		goto err_no_irq;
	netif_wake_queue(nic->netdev);
	napi_enable(&nic->napi);
	/* enable ints _after_ enabling poll, preventing a race between
	 * disable ints+schedule */
	e100_enable_irq(nic);
	return 0;

err_no_irq:
	del_timer_sync(&nic->watchdog);
err_clean_cbs:
	e100_clean_cbs(nic);
err_rx_clean_list:
	e100_rx_clean_list(nic);
	return err;
}

static void e100_down(struct nic *nic)
{
	/* wait here for poll to complete */
	napi_disable(&nic->napi);
	netif_stop_queue(nic->netdev);
	e100_hw_reset(nic);
	free_irq(nic->pdev->irq, nic->netdev);
	del_timer_sync(&nic->watchdog);
	netif_carrier_off(nic->netdev);
	e100_clean_cbs(nic);
	e100_rx_clean_list(nic);
}

static void e100_tx_timeout(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);

	/* Reset outside of interrupt context, to avoid request_irq
	 * in interrupt context */
	schedule_work(&nic->tx_timeout_task);
}

static void e100_tx_timeout_task(struct work_struct *work)
{
	struct nic *nic = container_of(work, struct nic, tx_timeout_task);
	struct net_device *netdev = nic->netdev;

	DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
		ioread8(&nic->csr->scb.status));
	e100_down(netdev_priv(netdev));
	e100_up(netdev_priv(netdev));
}

static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
{
	int err;
	struct sk_buff *skb;

	/* Use driver resources to perform internal MAC or PHY
	 * loopback test.  A single packet is prepared and transmitted
	 * in loopback mode, and the test passes if the received
	 * packet compares byte-for-byte to the transmitted packet. */

	if ((err = e100_rx_alloc_list(nic)))
		return err;
	if ((err = e100_alloc_cbs(nic)))
		goto err_clean_rx;

	/* ICH PHY loopback is broken so do MAC loopback instead */
	if (nic->flags & ich && loopback_mode == lb_phy)
		loopback_mode = lb_mac;

	nic->loopback = loopback_mode;
	if ((err = e100_hw_init(nic)))
		goto err_loopback_none;

	if (loopback_mode == lb_phy)
		mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
			BMCR_LOOPBACK);

	e100_start_receiver(nic, NULL);

	if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
		err = -ENOMEM;
		goto err_loopback_none;
	}
	skb_put(skb, ETH_DATA_LEN);
	memset(skb->data, 0xFF, ETH_DATA_LEN);
	e100_xmit_frame(skb, nic->netdev);

	msleep(10);

	pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
			RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);

	if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
	   skb->data, ETH_DATA_LEN))
		err = -EAGAIN;

err_loopback_none:
	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
	nic->loopback = lb_none;
	e100_clean_cbs(nic);
	e100_hw_reset(nic);
err_clean_rx:
	e100_rx_clean_list(nic);
	return err;
}

#define MII_LED_CONTROL	0x1B
#define E100_82552_LED_OVERRIDE 0x19
#define E100_82552_LED_ON       0x000F /* LEDTX and LED_RX both on */
#define E100_82552_LED_OFF      0x000A /* LEDTX and LED_RX both off */
static void e100_blink_led(unsigned long data)
{
	struct nic *nic = (struct nic *)data;
	enum led_state {
		led_on     = 0x01,
		led_off    = 0x04,
		led_on_559 = 0x05,
		led_on_557 = 0x07,
	};
	u16 led_reg = MII_LED_CONTROL;

	if (nic->phy == phy_82552_v) {
		led_reg = E100_82552_LED_OVERRIDE;

		nic->leds = (nic->leds == E100_82552_LED_ON) ?
		            E100_82552_LED_OFF : E100_82552_LED_ON;
	} else {
		nic->leds = (nic->leds & led_on) ? led_off :
		            (nic->mac < mac_82559_D101M) ? led_on_557 :
		            led_on_559;
	}
	mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds);
	mod_timer(&nic->blink_timer, jiffies + HZ / 4);
}

static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
	struct nic *nic = netdev_priv(netdev);
	return mii_ethtool_gset(&nic->mii, cmd);
}

static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
	struct nic *nic = netdev_priv(netdev);
	int err;

	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET);
	err = mii_ethtool_sset(&nic->mii, cmd);
	e100_exec_cb(nic, NULL, e100_configure);

	return err;
}

static void e100_get_drvinfo(struct net_device *netdev,
	struct ethtool_drvinfo *info)
{
	struct nic *nic = netdev_priv(netdev);
	strcpy(info->driver, DRV_NAME);
	strcpy(info->version, DRV_VERSION);
	strcpy(info->fw_version, "N/A");
	strcpy(info->bus_info, pci_name(nic->pdev));
}

#define E100_PHY_REGS 0x1C
static int e100_get_regs_len(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf);
}

static void e100_get_regs(struct net_device *netdev,
	struct ethtool_regs *regs, void *p)
{
	struct nic *nic = netdev_priv(netdev);
	u32 *buff = p;
	int i;

	regs->version = (1 << 24) | nic->pdev->revision;
	buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
		ioread8(&nic->csr->scb.cmd_lo) << 16 |
		ioread16(&nic->csr->scb.status);
	for (i = E100_PHY_REGS; i >= 0; i--)
		buff[1 + E100_PHY_REGS - i] =
			mdio_read(netdev, nic->mii.phy_id, i);
	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
	e100_exec_cb(nic, NULL, e100_dump);
	msleep(10);
	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
		sizeof(nic->mem->dump_buf));
}

static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
	struct nic *nic = netdev_priv(netdev);
	wol->supported = (nic->mac >= mac_82558_D101_A4) ?  WAKE_MAGIC : 0;
	wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0;
}

static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
	struct nic *nic = netdev_priv(netdev);

	if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) ||
	    !device_can_wakeup(&nic->pdev->dev))
		return -EOPNOTSUPP;

	if (wol->wolopts)
		nic->flags |= wol_magic;
	else
		nic->flags &= ~wol_magic;

	device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts);

	e100_exec_cb(nic, NULL, e100_configure);

	return 0;
}

static u32 e100_get_msglevel(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	return nic->msg_enable;
}

static void e100_set_msglevel(struct net_device *netdev, u32 value)
{
	struct nic *nic = netdev_priv(netdev);
	nic->msg_enable = value;
}

static int e100_nway_reset(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	return mii_nway_restart(&nic->mii);
}

static u32 e100_get_link(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	return mii_link_ok(&nic->mii);
}

static int e100_get_eeprom_len(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	return nic->eeprom_wc << 1;
}

#define E100_EEPROM_MAGIC	0x1234
static int e100_get_eeprom(struct net_device *netdev,
	struct ethtool_eeprom *eeprom, u8 *bytes)
{
	struct nic *nic = netdev_priv(netdev);

	eeprom->magic = E100_EEPROM_MAGIC;
	memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len);

	return 0;
}

static int e100_set_eeprom(struct net_device *netdev,
	struct ethtool_eeprom *eeprom, u8 *bytes)
{
	struct nic *nic = netdev_priv(netdev);

	if (eeprom->magic != E100_EEPROM_MAGIC)
		return -EINVAL;

	memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);

	return e100_eeprom_save(nic, eeprom->offset >> 1,
		(eeprom->len >> 1) + 1);
}

static void e100_get_ringparam(struct net_device *netdev,
	struct ethtool_ringparam *ring)
{
	struct nic *nic = netdev_priv(netdev);
	struct param_range *rfds = &nic->params.rfds;
	struct param_range *cbs = &nic->params.cbs;

	ring->rx_max_pending = rfds->max;
	ring->tx_max_pending = cbs->max;
	ring->rx_mini_max_pending = 0;
	ring->rx_jumbo_max_pending = 0;
	ring->rx_pending = rfds->count;
	ring->tx_pending = cbs->count;
	ring->rx_mini_pending = 0;
	ring->rx_jumbo_pending = 0;
}

static int e100_set_ringparam(struct net_device *netdev,
	struct ethtool_ringparam *ring)
{
	struct nic *nic = netdev_priv(netdev);
	struct param_range *rfds = &nic->params.rfds;
	struct param_range *cbs = &nic->params.cbs;

	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
		return -EINVAL;

	if (netif_running(netdev))
		e100_down(nic);
	rfds->count = max(ring->rx_pending, rfds->min);
	rfds->count = min(rfds->count, rfds->max);
	cbs->count = max(ring->tx_pending, cbs->min);
	cbs->count = min(cbs->count, cbs->max);
	DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n",
	        rfds->count, cbs->count);
	if (netif_running(netdev))
		e100_up(nic);

	return 0;
}

static const char e100_gstrings_test[][ETH_GSTRING_LEN] = {
	"Link test     (on/offline)",
	"Eeprom test   (on/offline)",
	"Self test        (offline)",
	"Mac loopback     (offline)",
	"Phy loopback     (offline)",
};
#define E100_TEST_LEN	ARRAY_SIZE(e100_gstrings_test)

static void e100_diag_test(struct net_device *netdev,
	struct ethtool_test *test, u64 *data)
{
	struct ethtool_cmd cmd;
	struct nic *nic = netdev_priv(netdev);
	int i, err;

	memset(data, 0, E100_TEST_LEN * sizeof(u64));
	data[0] = !mii_link_ok(&nic->mii);
	data[1] = e100_eeprom_load(nic);
	if (test->flags & ETH_TEST_FL_OFFLINE) {

		/* save speed, duplex & autoneg settings */
		err = mii_ethtool_gset(&nic->mii, &cmd);

		if (netif_running(netdev))
			e100_down(nic);
		data[2] = e100_self_test(nic);
		data[3] = e100_loopback_test(nic, lb_mac);
		data[4] = e100_loopback_test(nic, lb_phy);

		/* restore speed, duplex & autoneg settings */
		err = mii_ethtool_sset(&nic->mii, &cmd);

		if (netif_running(netdev))
			e100_up(nic);
	}
	for (i = 0; i < E100_TEST_LEN; i++)
		test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;

	msleep_interruptible(4 * 1000);
}

static int e100_phys_id(struct net_device *netdev, u32 data)
{
	struct nic *nic = netdev_priv(netdev);
	u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
	              MII_LED_CONTROL;

	if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
	mod_timer(&nic->blink_timer, jiffies);
	msleep_interruptible(data * 1000);
	del_timer_sync(&nic->blink_timer);
	mdio_write(netdev, nic->mii.phy_id, led_reg, 0);

	return 0;
}

static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
	"tx_heartbeat_errors", "tx_window_errors",
	/* device-specific stats */
	"tx_deferred", "tx_single_collisions", "tx_multi_collisions",
	"tx_flow_control_pause", "rx_flow_control_pause",
	"rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets",
};
#define E100_NET_STATS_LEN	21
#define E100_STATS_LEN	ARRAY_SIZE(e100_gstrings_stats)

static int e100_get_sset_count(struct net_device *netdev, int sset)
{
	switch (sset) {
	case ETH_SS_TEST:
		return E100_TEST_LEN;
	case ETH_SS_STATS:
		return E100_STATS_LEN;
	default:
		return -EOPNOTSUPP;
	}
}

static void e100_get_ethtool_stats(struct net_device *netdev,
	struct ethtool_stats *stats, u64 *data)
{
	struct nic *nic = netdev_priv(netdev);
	int i;

	for (i = 0; i < E100_NET_STATS_LEN; i++)
		data[i] = ((unsigned long *)&netdev->stats)[i];

	data[i++] = nic->tx_deferred;
	data[i++] = nic->tx_single_collisions;
	data[i++] = nic->tx_multiple_collisions;
	data[i++] = nic->tx_fc_pause;
	data[i++] = nic->rx_fc_pause;
	data[i++] = nic->rx_fc_unsupported;
	data[i++] = nic->tx_tco_frames;
	data[i++] = nic->rx_tco_frames;
}

static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
	switch (stringset) {
	case ETH_SS_TEST:
		memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
		break;
	case ETH_SS_STATS:
		memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats));
		break;
	}
}

static const struct ethtool_ops e100_ethtool_ops = {
	.get_settings		= e100_get_settings,
	.set_settings		= e100_set_settings,
	.get_drvinfo		= e100_get_drvinfo,
	.get_regs_len		= e100_get_regs_len,
	.get_regs		= e100_get_regs,
	.get_wol		= e100_get_wol,
	.set_wol		= e100_set_wol,
	.get_msglevel		= e100_get_msglevel,
	.set_msglevel		= e100_set_msglevel,
	.nway_reset		= e100_nway_reset,
	.get_link		= e100_get_link,
	.get_eeprom_len		= e100_get_eeprom_len,
	.get_eeprom		= e100_get_eeprom,
	.set_eeprom		= e100_set_eeprom,
	.get_ringparam		= e100_get_ringparam,
	.set_ringparam		= e100_set_ringparam,
	.self_test		= e100_diag_test,
	.get_strings		= e100_get_strings,
	.phys_id		= e100_phys_id,
	.get_ethtool_stats	= e100_get_ethtool_stats,
	.get_sset_count		= e100_get_sset_count,
};

static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
	struct nic *nic = netdev_priv(netdev);

	return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL);
}

static int e100_alloc(struct nic *nic)
{
	nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem),
		&nic->dma_addr);
	return nic->mem ? 0 : -ENOMEM;
}

static void e100_free(struct nic *nic)
{
	if (nic->mem) {
		pci_free_consistent(nic->pdev, sizeof(struct mem),
			nic->mem, nic->dma_addr);
		nic->mem = NULL;
	}
}

static int e100_open(struct net_device *netdev)
{
	struct nic *nic = netdev_priv(netdev);
	int err = 0;

	netif_carrier_off(netdev);
	if ((err = e100_up(nic)))
		DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n");
	return err;
}

static int e100_close(struct net_device *netdev)
{
	e100_down(netdev_priv(netdev));
	return 0;
}

static const struct net_device_ops e100_netdev_ops = {
	.ndo_open		= e100_open,
	.ndo_stop		= e100_close,
	.ndo_start_xmit		= e100_xmit_frame,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_multicast_list	= e100_set_multicast_list,
	.ndo_set_mac_address	= e100_set_mac_address,
	.ndo_change_mtu		= e100_change_mtu,
	.ndo_do_ioctl		= e100_do_ioctl,
	.ndo_tx_timeout		= e100_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= e100_netpoll,
#endif
};

static int __devinit e100_probe(struct pci_dev *pdev,
	const struct pci_device_id *ent)
{
	struct net_device *netdev;
	struct nic *nic;
	int err;

	if (!(netdev = alloc_etherdev(sizeof(struct nic)))) {
		if (((1 << debug) - 1) & NETIF_MSG_PROBE)
			printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n");
		return -ENOMEM;
	}

	netdev->netdev_ops = &e100_netdev_ops;
	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);

	nic = netdev_priv(netdev);
	netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT);
	nic->netdev = netdev;
	nic->pdev = pdev;
	nic->msg_enable = (1 << debug) - 1;
	nic->mdio_ctrl = mdio_ctrl_hw;
	pci_set_drvdata(pdev, netdev);

	if ((err = pci_enable_device(pdev))) {
		DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n");
		goto err_out_free_dev;
	}

	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
		DPRINTK(PROBE, ERR, "Cannot find proper PCI device "
			"base address, aborting.\n");
		err = -ENODEV;
		goto err_out_disable_pdev;
	}

	if ((err = pci_request_regions(pdev, DRV_NAME))) {
		DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n");
		goto err_out_disable_pdev;
	}

	if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
		DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
		goto err_out_free_res;
	}

	SET_NETDEV_DEV(netdev, &pdev->dev);

	if (use_io)
		DPRINTK(PROBE, INFO, "using i/o access mode\n");

	nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr));
	if (!nic->csr) {
		DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
		err = -ENOMEM;
		goto err_out_free_res;
	}

	if (ent->driver_data)
		nic->flags |= ich;
	else
		nic->flags &= ~ich;

	e100_get_defaults(nic);

	/* locks must be initialized before calling hw_reset */
	spin_lock_init(&nic->cb_lock);
	spin_lock_init(&nic->cmd_lock);
	spin_lock_init(&nic->mdio_lock);

	/* Reset the device before pci_set_master() in case device is in some
	 * funky state and has an interrupt pending - hint: we don't have the
	 * interrupt handler registered yet. */
	e100_hw_reset(nic);

	pci_set_master(pdev);

	init_timer(&nic->watchdog);
	nic->watchdog.function = e100_watchdog;
	nic->watchdog.data = (unsigned long)nic;
	init_timer(&nic->blink_timer);
	nic->blink_timer.function = e100_blink_led;
	nic->blink_timer.data = (unsigned long)nic;

	INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task);

	if ((err = e100_alloc(nic))) {
		DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
		goto err_out_iounmap;
	}

	if ((err = e100_eeprom_load(nic)))
		goto err_out_free;

	e100_phy_init(nic);

	memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
	memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
	if (!is_valid_ether_addr(netdev->perm_addr)) {
		if (!eeprom_bad_csum_allow) {
			DPRINTK(PROBE, ERR, "Invalid MAC address from "
			        "EEPROM, aborting.\n");
			err = -EAGAIN;
			goto err_out_free;
		} else {
			DPRINTK(PROBE, ERR, "Invalid MAC address from EEPROM, "
			        "you MUST configure one.\n");
		}
	}

	/* Wol magic packet can be enabled from eeprom */
	if ((nic->mac >= mac_82558_D101_A4) &&
	   (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
		nic->flags |= wol_magic;
		device_set_wakeup_enable(&pdev->dev, true);
	}

	/* ack any pending wake events, disable PME */
	pci_pme_active(pdev, false);

	strcpy(netdev->name, "eth%d");
	if ((err = register_netdev(netdev))) {
		DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
		goto err_out_free;
	}

	DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n",
		(unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
		pdev->irq, netdev->dev_addr);

	return 0;

err_out_free:
	e100_free(nic);
err_out_iounmap:
	pci_iounmap(pdev, nic->csr);
err_out_free_res:
	pci_release_regions(pdev);
err_out_disable_pdev:
	pci_disable_device(pdev);
err_out_free_dev:
	pci_set_drvdata(pdev, NULL);
	free_netdev(netdev);
	return err;
}

static void __devexit e100_remove(struct pci_dev *pdev)
{
	struct net_device *netdev = pci_get_drvdata(pdev);

	if (netdev) {
		struct nic *nic = netdev_priv(netdev);
		unregister_netdev(netdev);
		e100_free(nic);
		pci_iounmap(pdev, nic->csr);
		free_netdev(netdev);
		pci_release_regions(pdev);
		pci_disable_device(pdev);
		pci_set_drvdata(pdev, NULL);
	}
}

#define E100_82552_SMARTSPEED   0x14   /* SmartSpeed Ctrl register */
#define E100_82552_REV_ANEG     0x0200 /* Reverse auto-negotiation */
#define E100_82552_ANEG_NOW     0x0400 /* Auto-negotiate now */
static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct nic *nic = netdev_priv(netdev);

	if (netif_running(netdev))
		e100_down(nic);
	netif_device_detach(netdev);

	pci_save_state(pdev);

	if ((nic->flags & wol_magic) | e100_asf(nic)) {
		/* enable reverse auto-negotiation */
		if (nic->phy == phy_82552_v) {
			u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
			                           E100_82552_SMARTSPEED);

			mdio_write(netdev, nic->mii.phy_id,
			           E100_82552_SMARTSPEED, smartspeed |
			           E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
		}
		*enable_wake = true;
	} else {
		*enable_wake = false;
	}

	pci_disable_device(pdev);
}

static int __e100_power_off(struct pci_dev *pdev, bool wake)
{
	if (wake)
		return pci_prepare_to_sleep(pdev);

	pci_wake_from_d3(pdev, false);
	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

#ifdef CONFIG_PM
static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
{
	bool wake;
	__e100_shutdown(pdev, &wake);
	return __e100_power_off(pdev, wake);
}

static int e100_resume(struct pci_dev *pdev)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct nic *nic = netdev_priv(netdev);

	pci_set_power_state(pdev, PCI_D0);
	pci_restore_state(pdev);
	/* ack any pending wake events, disable PME */
	pci_enable_wake(pdev, 0, 0);

	/* disable reverse auto-negotiation */
	if (nic->phy == phy_82552_v) {
		u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
		                           E100_82552_SMARTSPEED);

		mdio_write(netdev, nic->mii.phy_id,
		           E100_82552_SMARTSPEED,
		           smartspeed & ~(E100_82552_REV_ANEG));
	}

	netif_device_attach(netdev);
	if (netif_running(netdev))
		e100_up(nic);

	return 0;
}
#endif /* CONFIG_PM */

static void e100_shutdown(struct pci_dev *pdev)
{
	bool wake;
	__e100_shutdown(pdev, &wake);
	if (system_state == SYSTEM_POWER_OFF)
		__e100_power_off(pdev, wake);
}

/* ------------------ PCI Error Recovery infrastructure  -------------- */
/**
 * e100_io_error_detected - called when PCI error is detected.
 * @pdev: Pointer to PCI device
 * @state: The current pci connection state
 */
static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct nic *nic = netdev_priv(netdev);

	netif_device_detach(netdev);

	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

	if (netif_running(netdev))
		e100_down(nic);
	pci_disable_device(pdev);

	/* Request a slot reset. */
	return PCI_ERS_RESULT_NEED_RESET;
}

/**
 * e100_io_slot_reset - called after the pci bus has been reset.
 * @pdev: Pointer to PCI device
 *
 * Restart the card from scratch.
 */
static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct nic *nic = netdev_priv(netdev);

	if (pci_enable_device(pdev)) {
		printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n");
		return PCI_ERS_RESULT_DISCONNECT;
	}
	pci_set_master(pdev);

	/* Only one device per card can do a reset */
	if (0 != PCI_FUNC(pdev->devfn))
		return PCI_ERS_RESULT_RECOVERED;
	e100_hw_reset(nic);
	e100_phy_init(nic);

	return PCI_ERS_RESULT_RECOVERED;
}

/**
 * e100_io_resume - resume normal operations
 * @pdev: Pointer to PCI device
 *
 * Resume normal operations after an error recovery
 * sequence has been completed.
 */
static void e100_io_resume(struct pci_dev *pdev)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct nic *nic = netdev_priv(netdev);

	/* ack any pending wake events, disable PME */
	pci_enable_wake(pdev, 0, 0);

	netif_device_attach(netdev);
	if (netif_running(netdev)) {
		e100_open(netdev);
		mod_timer(&nic->watchdog, jiffies);
	}
}

static struct pci_error_handlers e100_err_handler = {
	.error_detected = e100_io_error_detected,
	.slot_reset = e100_io_slot_reset,
	.resume = e100_io_resume,
};

static struct pci_driver e100_driver = {
	.name =         DRV_NAME,
	.id_table =     e100_id_table,
	.probe =        e100_probe,
	.remove =       __devexit_p(e100_remove),
#ifdef CONFIG_PM
	/* Power Management hooks */
	.suspend =      e100_suspend,
	.resume =       e100_resume,
#endif
	.shutdown =     e100_shutdown,
	.err_handler = &e100_err_handler,
};

static int __init e100_init_module(void)
{
	if (((1 << debug) - 1) & NETIF_MSG_DRV) {
		printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
		printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
	}
	return pci_register_driver(&e100_driver);
}

static void __exit e100_cleanup_module(void)
{
	pci_unregister_driver(&e100_driver);
}

module_init(e100_init_module);
module_exit(e100_cleanup_module);