Commit 3f102da8 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/net-drivers-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 7c165ccf 3ec5b5ab
Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
==============================================================
April 9, 2002
Contents
========
- In This Release
- Supported Adapters
- Command Line Parameters
- CPU Cycle Saver
- Additional Configurations
- Support
In This Release
===============
This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
Adapters, version 2.0.x. This driver includes support for Itanium(TM)-based
systems.
New for this release:
- Additional ethtool functionality, including link status test and EEPROM
read/write. A third-party application can use the ethtool interface to
get and set driver parameters.
- Support for Zero copy on 82550-based adapters. This feature provides
faster data throughput and significant CPU usage improvement in systems
that use the relevant system call (sendfile(2)).
- Support for large MTU-enabling interface (1504 bytes) with kernel's
VLAN module
- Support for polling on RX
- Support for Wake On LAN* on 82550 and 82559-based adapters
Supported Adapters
==================
The following Intel network adapters are compatible with the drivers
in this release:
Controller Adapter Name Board IDs
---------- ------------ ---------
82558 PRO/100+ PCI Adapter 668081-xxx, 689661-xxx
82558 PRO/100+ Management Adapter 691334-xxx, 701738-xxx,
721383-xxx
82558 PRO/100+ Dual Port Server Adapter 714303-xxx, 711269-xxx,
A28276-xxx
82558 PRO/100+ PCI Server Adapter 710550-xxx
82550 PRO/100 S Server Adapter 752438-xxx (82550)
82559 A56831-xxx, A10563-xxx,
A12171-xxx, A12321-xxx,
A12320-xxx, A12170-xxx
748568-xxx (82559)
748565-xxx (82559)
82550 PRO/100 S Desktop Adapter 751767-xxx (82550)
82559 748592-xxx, A12167-xxx,
A12318-xxx, A12317-xxx,
A12165-xxx
748569-xxx (82559)
82559 PRO/100+ Server Adapter 729757-xxx
82559 PRO/100 S Management Adapter 748566-xxx, 748564-xxx
82550 PRO/100 S Dual Port Server Adapter A56831-xxx
82551 PRO/100 M Desktop Adapter A80897-xxx
PRO/100 S Advanced Management Adapter 747842-xxx, 745171-xxx
CNR PRO/100 VE Desktop Adapter A10386-xxx, A10725-xxx,
A23801-xxx, A19716-xxx
PRO/100 VM Desktop Adapter A14323-xxx, A19725-xxx,
A23801-xxx, A22220-xxx,
A23796-xxx
To verify that your adapter is supported, find the board ID number on the
adapter. Look for a label that has a barcode and a number in the format
123456-001 (six digits hyphen three digits). Match this to the list of
numbers above.
For more information on how to identify your adapter, go to the Adapter &
Driver ID Guide at:
http://support.intel.com/support/network/adapter/pro100/21397.htm
For the latest Intel PRO/100 network driver for Linux, see:
http://appsr.intel.com/scripts-df/support_intel.asp
Command Line Parameters
=======================
The following parameters are used by entering them on the command line with
the modprobe or insmod command. For example, with two Intel PRO/100 PCI
adapters, entering:
modprobe e100 TxDescriptors=32,128
loads the e100 driver with 32 TX resources for the first adapter and 128 TX
resources for the second adapter. This configuration favors the second
adapter. The driver supports up to 16 network adapters concurrently.
NOTE: Giving any command line option the value "-1" causes the driver to use
the appropriate default value for that option, as if no value was
specified.
BundleMax
Valid Range: 0x1-0xFFFF
Default Value: 6
This parameter holds the maximum number of packets in a bundle. Suggested
values range from 2 to 10. See "CPU Cycle Saver."
BundleSmallFr
Valid Range: 0-1 (0=off, 1=on)
Default Value: 0
The value 1 (on) causes small packets (less than 128 bytes) to be bundled.
See "CPU Cycle Saver."
e100_speed_duplex
Valid Range: 0-4 (1=10half;2=10full;3=100half;4=100full)
Default Value: 0
The default value of 0 is set to auto-negotiate if the link partner is set
to auto-negotiate. If the link partner is forced, e100_speed_duplex
defaults to half-duplex.
Example usage: insmod e100.o e100_speed_duplex=4,4 (for two adapters)
flow_control
Valid Range: 0-1 (0=off, 1=on)
Default Value: 0
This parameter controls the automatic generation(Tx) and response(Rx) to
Ethernet PAUSE frames. flow_control should NOT be set to 1 when the e100
adapter is connected to an interface that does not support Ethernet PAUSE
frames and when the e100_speed_duplex parameter is NOT set to zero.
IntDelay
Valid Range: 0-0xFFFF (0=off)
Default Value: 1536
This parameter holds the number of time units (in adapter terminology)
until the adapter generates an interrupt. The recommended value for
IntDelay is 0x600 (upon initialization). Suggested values range from
0x200h to 0x800. See "CPU Cycle Saver."
IFS
Valid Range: 0-1 (0=off, 1=on)
Default Value: 1
Inter Frame Spacing (IFS) aims to reduce the number of Ethernet frame
collisions by altering the time between frame transmissions. When IFS is
enabled the driver tries to find an optimal IFS value. However, some
switches function better when IFS is disabled.
PollingMaxWork
Valid Range: 1-1024 (max number of RxDescriptors)
Default Value: Specified number of RxDescriptors
This value specifies the maximum number of receive packets that are
processed on a single polling call. This parameter is invalid if
RxCongestionControl is set to 0.
RxCongestionControl
Valid Range: 0-1 (0=off, 1=on)
Default Value: 1
1 enables polling mode. When the link is congested, the driver can decide
to handle received packets by polling them, instead of waiting until
interrupts occur.
RxDescriptors
Valid Range: 8-1024
Default Value: 64
This parameter defines the number of receive descriptors allocated by
the driver. Increasing this value allows the driver to buffer more
incoming packets before the driver is required to service an interrupt.
The maximum value for Itanium-based systems is 64.
TxDescriptors
Valid Range: 19-1024
Default Value: 64
This value is the number of transmit descriptors allocated by the driver.
Increasing this value allows the protocol stack to queue more transmits at
the driver level. The maximum value for Itanium-based systems is 64.
ucode (not available for 82557-based adapters)
Valid Range: 0-1 (0=off, 1=on)
Default Value: 0 for 82558-based adapters
1 for 82559(and higher)-based adapters
On uploads the micro code to the adapter, which enables CPU Cycle Saver.
See the section "CPU Cycle Saver" below.
Example usage: insmod e100.o ucode=0 (does not reduce CPU usage)
XsumRX
Valid Range: 0-1 (0=off, 1=on)
Default Value: 1
On allows Rx checksum offloading for TCP/UDP packets. Requires that the
hardware support this feature.
CPU Cycle Saver
================
CPU Cycle Saver reduces CPU utilization by reducing the number of interrupts
that the adapter generates.
When CPU Cycle Saver is turned off, the adapter generates one interrupt for
every frame that is received. This means that the operating system stops what
it is doing and switches to the network driver in order to process the
receive.
When CPU Cycle Saver is on, the adapter does not generate an interrupt for
every frame it receives. Instead, it waits until it receives several frames
before generating an interrupt. This reduces the amount of time spent
switching to and from the driver.
CPU Cycle Saver consists of these arguments: IntDelay, BundleMax and
BundleSmallFr. When IntDelay is increased, the adapter waits longer for
frames to arrive before generating the interrupt. By increasing BundleMax,
the network adapter waits for the number of frames specified to arrive before
generating the interrupt. When BundleSmallFr is disabled, the adapter does
not bundle packets that are smaller than 128 bytes. Such small packets are
often, but not always, control packets that are better served immediately.
For most users, it is recommended that CPU Cycle Saver be used with the
default values specified in the Command Line Parameters section. However, in
some cases, performance problems may occur with CPU Cycle Saver. If such
problems are observed, we recommend turning off this feature by setting
ucode=0.
Support
=======
For general information and support, go to the Intel support website at:
http://support.intel.com
If an issue is identified with the released source code on the supported
kernel with a supported adapter, email the specific information related to
the issue to linux.nics@intel.com.
License
=======
This software program is released under the terms of a license agreement
between you ('Licensee') and Intel. Do not use or load this software or any
associated materials (collectively, the 'Software') until you have carefully
read the full terms and conditions of the LICENSE located in this software
package. By loading or using the Software, you agree to the terms of this
Agreement. If you do not agree with the terms of this Agreement, do not
install or use the Software.
* Other names and brands may be claimed as the property of others.
Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
===============================================================
February 5, 2002
April 23, 2002
Contents
......@@ -11,6 +11,7 @@ Contents
- Supported Adapters
- Command Line Parameters
- Speed and Duplex Configuration
- Additional Configurations
- Known Issues
- Support
......@@ -19,17 +20,27 @@ In This Release
===============
This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
of Adapters, version 4.2.x.
This driver includes support for Itanium(TM)-based systems.
of Adapters, version 4.2.x. This driver includes support for
Itanium(TM)-based systems.
This release version includes the following:
- support for the ethtool 1.4 interface. A third-party application can use
- Support for the ethtool 1.5 interface. A third-party application can use
the ethtool interface to get and set driver parameters.
- the zero copy feature. Zero copy provides faster information throughput.
By default, this feature is enabled if using a kernel that supports it.
Zero copy is not supported on the original PWLA8490 (plain) adapter.
- Zero copy. This feature provides faster data throughput. Enabled by
default in supporting kernels. It is not supported on the Intel(R)
PRO/1000 Gigabit Server Adapter.
New features include:
- Support for the 82545 and 82546-based adapters listed below
- Wake on LAN* support via ethtool for 82540, 82544, 82545, and 82546-
based adapters
- Adaptive IFS for increased performance at half duplex
Supported Adapters
......@@ -43,8 +54,7 @@ release:
82542 PRO/1000 Gigabit Server Adapter 700262-xxx, 717037-xxx
82543 PRO/1000 F Server Adapter 738640-xxx, A38888-xxx,
A06512-xxx
82543 PRO/1000 F Server Adapter 738640-xxx, A38888-xxx
82543 PRO/1000 T Server Adapter A19845-xxx, A33948-xxx
......@@ -54,6 +64,18 @@ release:
82544 PRO/1000 T Desktop Adapter A62947-xxx
82540 PRO/1000 MT Desktop Adapter A78408-xxx
82545 PRO/1000 MT Server Adapter A92165-xxx
82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx
82545 PRO/1000 MF Server Adapter A91622-xxx
82545 PRO/1000 MF Server Adapter(LX) A91624-xxx
82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx
To verify your Intel adapter is supported, find the board ID number on the
adapter. Look for a label that has a barcode and a number in the format of
......@@ -86,14 +108,14 @@ For more information about the AutoNeg, Duplex, and Speed parameters, see the
"Speed and Duplex Configuration" section in this document.
AutoNeg (Intel PRO/1000 T and PRO/1000 XT server adapters only)
Valid Range: 0-0x0F, 0x20-0x2F
AutoNeg (adapters using copper connections only)
Valid Range: 0x01-0x0F, 0x20-0x2F
Default Value: 0x2F
This parameter is a bit mask that specifies which speed and duplex
settings the board advertises. When this parameter is used, the Speed and
Duplex parameters must not be specified.
Duplex (Intel PRO/1000 T and PRO/1000 XT server adapters only)
Duplex (adapters using copper connections only)
Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full)
Default Value: 0
Defines the direction in which data is allowed to flow. Can by either one
......@@ -109,17 +131,18 @@ Default: Read flow control settings from the EEPROM
RxDescriptors
Valid Range: 80-256 for 82542 and 82543-based adapters
80-4096 for 82544-based adapters
Default Value: 256
80-4096 for 82540, 82544, 82545, and 82546-based adapters
Default Value: 80
This value is the number of receive descriptors allocated by the driver.
Increasing this value allows the driver to buffer more incoming packets.
Each descriptor is 16 bytes. A receive buffer is also allocated for each
descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
on the MTU setting.
on the MTU setting. The maximum MTU size is 16110.
RxIntDelay
Valid Range: 0-65535 (0=off)
Default Value: 64
Default Value: 64 (82542, 82543, and 82544-based adapters)
128 (82540, 82545, and 82546-based adapters)
This value delays the generation of receive interrupts in units of 1.024
microseconds. Receive interrupt reduction can improve CPU efficiency if
properly tuned for specific network traffic. Increasing this value adds
......@@ -128,7 +151,7 @@ Default Value: 64
may be set too high, causing the driver to run out of available receive
descriptors.
Speed (Intel PRO/1000 T and PRO/1000 XT server adapters only)
Speed (adapters using copper connections only)
Valid Settings: 0, 10, 100, 1000
Default Value: 0 (auto-negotiate at all supported speeds)
Speed forces the line speed to the specified value in megabits per second
......@@ -138,21 +161,12 @@ Default Value: 0 (auto-negotiate at all supported speeds)
TxDescriptors
Valid Range: 80-256 for 82542 and 82543-based adapters
80-4096 for 82544-based adapters
80-4096 for 82540, 82544, 82545, and 82546-based adapters
Default Value: 256
This value is the number of transmit descriptors allocated by the driver.
Increasing this value allows the driver to queue more transmits. Each
descriptor is 16 bytes.
TxIntDelay
Valid Range: 0-65535 (0=off)
Default Value: 64
This value delays the generation of transmit interrupts in units of 1.024
microseconds. Transmit interrupt reduction can improve CPU efficiency if
properly tuned for specific network traffic. If the system is reporting
dropped transmits, this value may be set too high causing the driver to
run out of available transmit descriptors.
XsumRX (not available on the PRO/1000 Gigabit Server Adapter)
Valid Range: 0-1
Default Value: 1
......@@ -163,9 +177,8 @@ Default Value: 1
Speed and Duplex Configuration
==============================
Three keywords are used to control the speed and duplex configuration of the
PRO/1000 T and PRO/1000 XT server adapters. These keywords are Speed, Duplex,
and AutoNeg.
Three keywords are used to control the speed and duplex configuration. These
keywords are Speed, Duplex, and AutoNeg.
If the board uses a fiber interface, these keywords are ignored, and the
fiber interface board only links at 1000 Mbps full-duplex.
......@@ -199,16 +212,32 @@ set to auto-negotiate. If the link partner is forced speed/duplex, the
adapter MUST be forced to the same speed/duplex.
Additional Configurations
=========================
Jumbo Frames
------------
The driver supports Jumbo Frames for all adapters except 82542-based
adapters. Jumbo Frames support is enabled by changing the MTU to a value
larger than the default of 1500. Use the ifconfig command to increase the
MTU size. For example:
ifconfig ethx mtu 9000 up
Known Issues
============
Driver Hangs Under Heavy Traffic Loads
--------------------------------------
Inconsistent Driver Behavior Under Heavy Traffic Loads
------------------------------------------------------
Intel is aware that previously released e1000 drivers may hang under very
specific types of heavy traffic loads. This version includes a workaround
that resets the adapter automatically if a hang condition is detected. This
workaround ensures network traffic flow is not affected when a hang occurs.
Adapters based on the Intel 82543 and 82544 LAN controllers may hang (stop
transmitting) under certain network conditions. If this occurs a message
is logged in the system event log. In addition, the controller is
automatically reset, restoring the network connection. To eliminate the
potential for the hang change the RxIntDelay parameter to zero. For details
on the RxIntDelay parameter see the Command Line Parameters section.
Jumbo Frames System Requirement
-------------------------------
......
......@@ -795,6 +795,11 @@ P: Tigran Aivazian
M: tigran@veritas.com
S: Maintained
INTEL PRO/100 ETHERNET SUPPORT
P: Scott Feldman
M: scott.feldman@intel.com
S: Supported
INTEL PRO/1000 GIGABIT ETHERNET SUPPORT
P: Chris Leech
M: christopher.leech@intel.com
......
......@@ -833,13 +833,18 @@ CONFIG_E1000
82542 PRO/1000 Gigabit Server Adapter 700262-xxx,
717037-xxx
82543 PRO/1000 F Server Adapter 738640-xxx,
A38888-xxx,
A06512-xxx
A38888-xxx
82543 PRO/1000 T Server Adapter A19845-xxx,
A33948-xxx
82544 PRO/1000 XT Server Adapter A51580-xxx
82544 PRO/1000 XF Server Adapter A50484-xxx
82544 PRO/1000 T Desktop Adapter A62947-xxx
82540 PRO/1000 MT Desktop Adapter A78408-xxx
82545 PRO/1000 MT Server Adapter A92165-xxx
82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx
82545 PRO/1000 MF Server Adapter A91622-xxx
82545 PRO/1000 MF Server Adapter(LX) A91624-xxx
82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx
For more information on how to identify your adapter, go to the
Adapter & Driver ID Guide at:
......@@ -1358,6 +1363,80 @@ CONFIG_EEPRO100
a module, say M here and read <file:Documentation/modules.txt> as
well as <file:Documentation/networking/net-modules.txt>.
CONFIG_E100
This driver supports Intel(R) PRO/100 family of adapters, which
includes:
Controller Adapter Name Board IDs
---------- ------------ ---------
82558 PRO/100+ PCI Adapter 668081-xxx,
689661-xxx
82558 PRO/100+ Management Adapter 691334-xxx,
701738-xxx,
721383-xxx
82558 PRO/100+ Dual Port Server Adapter 714303-xxx,
711269-xxx,
A28276-xxx
82558 PRO/100+ PCI Server Adapter 710550-xxx
82550 PRO/100 S Server Adapter 752438-xxx
82559 A56831-xxx,
A10563-xxx,
A12171-xxx,
A12321-xxx,
A12320-xxx,
A12170-xxx
748568-xxx
748565-xxx
82550 PRO/100 S Desktop Adapter 751767-xxx
82559 748592-xxx,
A12167-xxx,
A12318-xxx,
A12317-xxx,
A12165-xxx,
748569-xxx
82559 PRO/100+ Server Adapter 729757-xxx
82559 PRO/100 S Management Adapter 748566-xxx,
748564-xxx
82550 PRO/100 S Dual Port Server Adapter A56831-xxx
82551 PRO/100 M Desktop Adapter A80897-xxx
PRO/100 S Advanced Management Adapter
747842-xxx,
745171-xxx
CNR PRO/100 VE Desktop Adapter A10386-xxx,
A10725-xxx,
A23801-xxx,
A19716-xxx
PRO/100 VM Desktop Adapter A14323-xxx,
A19725-xxx,
A23801-xxx,
A22220-xxx,
A23796-xxx
To verify that your adapter is supported, find the board ID number
on the adapter. Look for a label that has a barcode and a number
in the format 123456-001 (six digits hyphen three digits). Match
this to the list of numbers above.
For more information on how to identify your adapter, go to the
Adapter & Driver ID Guide at:
http://support.intel.com/support/network/adapter/pro100/21397.htm
For the latest Intel PRO/100 network driver for Linux, see:
http://appsr.intel.com/scripts-df/support_intel.asp
More specific information on configuring the driver is in
<file:Documentation/networking/e100.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called e100.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt> as well
as <file:Documentation/networking/net-modules.txt>.
CONFIG_FEALNX
Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet
cards. Specifications and data at
......
......@@ -29,24 +29,28 @@
1.08 2002/01/17 Fixed the multicast bug.
1.09 2002/03/07 Move rx-poll-now to re-fill loop.
Added rio_timer() to watch rx buffers.
1.10 2002/04/16 Fixed miscount of carrier error.
1.11 2002/05/23 Added ISR schedule scheme.
Fixed miscount of rx frame error for DGE-550SX.
Fixed VLAN bug.
*/
#include "dl2k.h"
static char version[] __devinitdata =
KERN_INFO "D-Link DL2000-based linux driver v1.09 2002/03/07\n";
KERN_INFO "D-Link DL2000-based linux driver v1.11 2002/05/23\n";
#define MAX_UNITS 8
static int mtu[MAX_UNITS];
static int vlan[MAX_UNITS];
static int jumbo[MAX_UNITS];
static char *media[MAX_UNITS];
static int tx_flow[MAX_UNITS];
static int rx_flow[MAX_UNITS];
static int tx_flow=-1;
static int rx_flow=-1;
static int copy_thresh;
static int rx_coalesce; /* Rx frame count each interrupt */
static int rx_timeout; /* Rx DMA wait time in 64ns increments */
static int tx_coalesce = DEFAULT_TXC; /* HW xmit count each TxComplete [1-8] */
static int rx_coalesce=10; /* Rx frame count each interrupt */
static int rx_timeout=200; /* Rx DMA wait time in 640ns increments */
static int tx_coalesce=16; /* HW xmit count each TxDMAComplete */
MODULE_AUTHOR ("Edward Peng");
......@@ -56,16 +60,16 @@ MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i");
MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
MODULE_PARM (tx_flow, "i");
MODULE_PARM (rx_flow, "i");
MODULE_PARM (copy_thresh, "i");
MODULE_PARM (rx_coalesce, "i"); /* Rx frame count each interrupt */
MODULE_PARM (rx_timeout, "i"); /* Rx DMA wait time in 64ns increments */
MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxComplete [1-8] */
MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxDMAComplete */
/* Enable the default interrupts */
#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxComplete| \
#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxDMAComplete| \
UpdateStats | LinkEvent)
#define EnableInt() \
writew(DEFAULT_INTR, ioaddr + IntEnable)
......@@ -75,16 +79,18 @@ static int multicast_filter_limit = 0x40;
static int rio_open (struct net_device *dev);
static void rio_timer (unsigned long data);
static void tx_timeout (struct net_device *dev);
static void rio_tx_timeout (struct net_device *dev);
static void alloc_list (struct net_device *dev);
static int start_xmit (struct sk_buff *skb, struct net_device *dev);
static void rio_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
static void rio_free_tx (struct net_device *dev, int irq);
static void tx_error (struct net_device *dev, int tx_status);
static int receive_packet (struct net_device *dev);
static void rio_error (struct net_device *dev, int int_status);
static int change_mtu (struct net_device *dev, int new_mtu);
static void set_multicast (struct net_device *dev);
static struct net_device_stats *get_stats (struct net_device *dev);
static int clear_stats (struct net_device *dev);
static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int rio_close (struct net_device *dev);
static int find_miiphy (struct net_device *dev);
......@@ -98,9 +104,6 @@ static int mii_get_media_pcs (struct net_device *dev);
static int mii_read (struct net_device *dev, int phy_addr, int reg_num);
static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
u16 data);
#ifdef RIO_DEBUG
static int rio_ioctl_ext (struct net_device *dev, struct ioctl_data *iodata);
#endif
static int __devinit
rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
......@@ -109,7 +112,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
struct netdev_private *np;
static int card_idx;
int chip_idx = ent->driver_data;
int err, irq = pdev->irq;
int err, irq;
long ioaddr;
static int version_printed;
void *ring_space;
......@@ -122,6 +125,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
return err;
irq = pdev->irq;
err = pci_request_regions (pdev, "dl2k");
if (err)
goto err_out_disable;
......@@ -149,7 +153,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
np = dev->priv;
np->chip_id = chip_idx;
np->pdev = pdev;
spin_lock_init (&np->lock);
spin_lock_init (&np->tx_lock);
spin_lock_init (&np->rx_lock);
/* Parse manual configuration */
......@@ -199,17 +203,18 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
}
np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ?
vlan[card_idx] : 0;
if (rx_coalesce != 0 && rx_timeout != 0) {
if (rx_coalesce > 0 && rx_timeout > 0) {
np->rx_coalesce = rx_coalesce;
np->rx_timeout = rx_timeout;
np->coalesce = 1;
}
np->tx_flow = (tx_flow[card_idx]) ? 1 : 0;
np->rx_flow = (rx_flow[card_idx]) ? 1 : 0;
np->tx_flow = (tx_flow == 0) ? 0 : 1;
np->rx_flow = (rx_flow == 0) ? 0 : 1;
if (tx_coalesce < 1)
tx_coalesce = 1;
if (tx_coalesce > 8)
tx_coalesce = 8;
if (tx_coalesce > TX_RING_SIZE-1)
tx_coalesce = TX_RING_SIZE - 1;
}
dev->open = &rio_open;
dev->hard_start_xmit = &start_xmit;
......@@ -217,7 +222,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->get_stats = &get_stats;
dev->set_multicast_list = &set_multicast;
dev->do_ioctl = &rio_ioctl;
dev->tx_timeout = &tx_timeout;
dev->tx_timeout = &rio_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->change_mtu = &change_mtu;
#if 0
......@@ -247,6 +252,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
/* Fiber device? */
np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0;
np->link_status = 0;
/* Set media and reset PHY */
if (np->phy_media) {
/* default 1000mbps_fd for fiber deivices */
......@@ -281,6 +287,15 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->name, np->name,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], irq);
if (tx_coalesce > 1)
printk(KERN_INFO "tx_coalesce:\t%d packets\n",
tx_coalesce);
if (np->coalesce)
printk(KERN_INFO "rx_coalesce:\t%d packets\n"
KERN_INFO "rx_timeout: \t%d ns\n",
np->rx_coalesce, np->rx_timeout*640);
if (np->vlan)
printk(KERN_INFO "vlan(id):\t%d\n", np->vlan);
return 0;
err_out_unmap_rx:
......@@ -327,7 +342,7 @@ find_miiphy (struct net_device *dev)
return 0;
}
static int __devinit
int
parse_eeprom (struct net_device *dev)
{
int i, j;
......@@ -431,8 +446,10 @@ rio_open (struct net_device *dev)
writeb (0xff, ioaddr + TxDMAPollPeriod);
writeb (0x30, ioaddr + RxDMABurstThresh);
writeb (0x30, ioaddr + RxDMAUrgentThresh);
netif_start_queue (dev);
writel (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl);
/* clear statistics */
clear_stats (dev);
/* VLAN supported */
if (np->vlan) {
/* priority field in RxDMAIntCtrl */
......@@ -451,15 +468,20 @@ rio_open (struct net_device *dev)
/* Enable default interrupts */
EnableInt ();
/* clear statistics */
get_stats (dev);
init_timer (&np->timer);
np->timer.expires = jiffies + 1*HZ;
np->timer.data = (unsigned long) dev;
np->timer.function = &rio_timer;
add_timer (&np->timer);
/* Start Tx/Rx */
writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
ioaddr + MACCtrl);
netif_start_queue (dev);
return 0;
}
static void
rio_timer (unsigned long data)
{
......@@ -469,10 +491,10 @@ rio_timer (unsigned long data)
int next_tick = 1*HZ;
unsigned long flags;
spin_lock_irqsave(&np->rx_lock, flags);
/* Recover rx ring exhausted error */
if (np->cur_rx - np->old_rx >= RX_RING_SIZE) {
printk(KERN_INFO "Try to recover rx ring exhausted...\n");
spin_lock_irqsave(&np->rx_lock, flags);
/* Re-allocate skbuffs to fill the descriptor ring */
for (; np->cur_rx - np->old_rx > 0; np->old_rx++) {
struct sk_buff *skb;
......@@ -500,43 +522,22 @@ rio_timer (unsigned long data)
cpu_to_le64 (np->rx_buf_sz) << 48;
np->rx_ring[entry].status = 0;
} /* end for */
spin_unlock_irqrestore (&np->rx_lock, flags);
} /* end if */
spin_unlock_irqrestore (&np->rx_lock, flags);
np->timer.expires = jiffies + next_tick;
add_timer(&np->timer);
}
static void
tx_timeout (struct net_device *dev)
rio_tx_timeout (struct net_device *dev)
{
struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
dev->name, readl (ioaddr + TxStatus));
/* Free used tx skbuffs */
for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
int entry = np->old_tx % TX_RING_SIZE;
struct sk_buff *skb;
if (!(np->tx_ring[entry].status & TFDDone))
break;
skb = np->tx_skbuff[entry];
pci_unmap_single (np->pdev,
np->tx_ring[entry].fraginfo,
skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb_irq (skb);
np->tx_skbuff[entry] = 0;
}
rio_free_tx(dev, 0);
dev->if_port = 0;
dev->trans_start = jiffies;
np->stats.tx_errors++;
/* If the ring is no longer full, clear tx_full and
call netif_wake_queue() */
if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
np->tx_full = 0;
netif_wake_queue (dev);
}
}
/* allocate and initialize Tx and Rx descriptors */
......@@ -546,7 +547,6 @@ alloc_list (struct net_device *dev)
struct netdev_private *np = dev->priv;
int i;
np->tx_full = 0;
np->cur_rx = np->cur_tx = 0;
np->old_rx = np->old_tx = 0;
np->rx_buf_sz = (dev->mtu <= 1500 ? PACKET_SIZE : dev->mtu + 32);
......@@ -605,18 +605,17 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
struct netdev_desc *txdesc;
unsigned entry;
u32 ioaddr;
int tx_shift;
unsigned long flags;
u64 tfc_vlan_tag = 0;
if (np->link_status == 0) { /* Link Down */
dev_kfree_skb(skb);
return 0;
}
ioaddr = dev->base_addr;
entry = np->cur_tx % TX_RING_SIZE;
np->tx_skbuff[entry] = skb;
txdesc = &np->tx_ring[entry];
/* Set TFDDone to avoid TxDMA gather this descriptor */
txdesc->status = cpu_to_le64 (TFDDone);
txdesc->status |=
cpu_to_le64 (entry | WordAlignDisable | (1 << FragCountShift));
#if 0
if (skb->ip_summed == CHECKSUM_HW) {
txdesc->status |=
......@@ -630,31 +629,33 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
(cpu_to_le64 (np->vlan) << 32) |
(cpu_to_le64 (skb->priority) << 45);
}
/* Send one packet each time at 10Mbps mode */
/* Tx coalescing loop do not exceed 8 */
if (entry % tx_coalesce == 0 || np->speed == 10)
txdesc->status |= cpu_to_le64 (TxIndicate);
txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data,
skb->len,
PCI_DMA_TODEVICE));
txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48;
/* Clear TFDDone, then TxDMA start to send this descriptor */
txdesc->status &= ~cpu_to_le64 (TFDDone);
DEBUG_TFD_DUMP (np);
/* DL2K bug: DMA fails to get next descriptor ptr in 10Mbps mode
* Work around: Always use 1 descriptor in 10Mbps mode */
if (entry % tx_coalesce == 0 || np->speed == 10)
txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
WordAlignDisable |
TxDMAIndicate |
(1 << FragCountShift));
else
txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
WordAlignDisable |
(1 << FragCountShift));
/* TxDMAPollNow */
writel (readl (ioaddr + DMACtrl) | 0x00001000, ioaddr + DMACtrl);
np->cur_tx++;
if (np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1 && np->speed != 10) {
/* Schedule ISR */
writel(10000, ioaddr + CountDown);
np->cur_tx = (np->cur_tx + 1) % TX_RING_SIZE;
if ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
< TX_QUEUE_LEN - 1 && np->speed != 10) {
/* do nothing */
} else {
spin_lock_irqsave(&np->lock, flags);
np->tx_full = 1;
} else if (!netif_queue_stopped(dev)) {
netif_stop_queue (dev);
spin_unlock_irqrestore (&np->lock, flags);
}
/* The first TFDListPtr */
......@@ -664,14 +665,6 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
writel (0, dev->base_addr + TFDListPtr1);
}
if (np->old_tx > TX_RING_SIZE) {
spin_lock_irqsave (&np->lock, flags);
tx_shift = TX_RING_SIZE;
np->old_tx -= tx_shift;
np->cur_tx -= tx_shift;
spin_unlock_irqrestore (&np->lock, flags);
}
/* NETDEV WATCHDOG timer */
dev->trans_start = jiffies;
return 0;
......@@ -688,25 +681,48 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
ioaddr = dev->base_addr;
np = dev->priv;
spin_lock(&np->lock);
while (1) {
int_status = readw (ioaddr + IntStatus);
writew (int_status, ioaddr + IntStatus);
int_status &= DEFAULT_INTR;
if (int_status == 0)
if (int_status == 0 || --cnt < 0)
break;
/* Processing received packets */
if (int_status & RxDMAComplete)
receive_packet (dev);
/* TxComplete interrupt */
if ((int_status & TxComplete) || np->tx_full) {
/* TxDMAComplete interrupt */
if ((int_status & (TxDMAComplete|IntRequested))) {
int tx_status;
tx_status = readl (ioaddr + TxStatus);
if (tx_status & 0x01)
tx_error (dev, tx_status);
/* Free used tx skbuffs */
for (;np->cur_tx - np->old_tx > 0; np->old_tx++) {
rio_free_tx (dev, 1);
}
/* Handle uncommon events */
if (int_status &
(HostError | LinkEvent | UpdateStats))
rio_error (dev, int_status);
}
if (np->cur_tx != np->old_tx)
writel (100, ioaddr + CountDown);
}
static void
rio_free_tx (struct net_device *dev, int irq)
{
struct netdev_private *np = (struct netdev_private *) dev->priv;
int entry = np->old_tx % TX_RING_SIZE;
int tx_use = 0;
long flag = 0;
if (irq)
spin_lock_irqsave(&np->tx_lock, flag);
else
spin_lock(&np->tx_lock);
/* Free used tx skbuffs */
while (entry != np->cur_tx) {
struct sk_buff *skb;
if (!(np->tx_ring[entry].status & TFDDone))
......@@ -715,34 +731,29 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
pci_unmap_single (np->pdev,
np->tx_ring[entry].fraginfo,
skb->len, PCI_DMA_TODEVICE);
if (irq)
dev_kfree_skb_irq (skb);
else
dev_kfree_skb (skb);
np->tx_skbuff[entry] = 0;
entry = (entry + 1) % TX_RING_SIZE;
tx_use++;
}
}
if (irq)
spin_unlock_irqrestore(&np->tx_lock, flag);
else
spin_unlock(&np->tx_lock);
np->old_tx = entry;
/* If the ring is no longer full, clear tx_full and
call netif_wake_queue() */
if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
if (np->speed != 10 || int_status & TxComplete) {
np->tx_full = 0;
netif_wake_queue (dev);
}
}
/* Handle uncommon events */
if (int_status &
(IntRequested | HostError | LinkEvent | UpdateStats))
rio_error (dev, int_status);
/* If too much interrupts here, disable all interrupts except
IntRequest. When CountDown down to 0, IntRequest will
be caught by rio_error() to recovery the interrupts */
if (--cnt < 0) {
get_stats (dev);
writel (1, ioaddr + CountDown);
writew (IntRequested, ioaddr + IntEnable);
break;
}
if (netif_queue_stopped(dev) &&
((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
< TX_QUEUE_LEN - 1 || np->speed == 10)) {
netif_wake_queue (dev);
}
spin_unlock(&np->lock);
}
static void
......@@ -755,11 +766,10 @@ tx_error (struct net_device *dev, int tx_status)
np = dev->priv;
frame_id = (tx_status & 0xffff0000) >> 16;
frame_id = (tx_status & 0xffff0000);
printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
dev->name, tx_status, frame_id);
np->stats.tx_errors++;
np->stats.tx_dropped++;
/* Ttransmit Underrun */
if (tx_status & 0x10) {
np->stats.tx_fifo_errors++;
......@@ -774,20 +784,7 @@ tx_error (struct net_device *dev, int tx_status)
break;
mdelay (1);
}
/* Free completed descriptors */
for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
int entry = np->old_tx % TX_RING_SIZE;
struct sk_buff *skb;
if (!(np->tx_ring[entry].status & TFDDone))
break;
skb = np->tx_skbuff[entry];
pci_unmap_single (np->pdev, np->tx_ring[entry].fraginfo,
skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb_irq (skb);
np->tx_skbuff[entry] = 0;
}
rio_free_tx (dev, 1);
/* Reset TFDListPtr */
writel (np->tx_ring_dma +
np->old_tx * sizeof (struct netdev_desc),
......@@ -817,7 +814,6 @@ tx_error (struct net_device *dev, int tx_status)
if (tx_status & 0x08)
np->stats.collisions++;
#endif
/* Restart the Tx */
writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
}
......@@ -827,16 +823,8 @@ receive_packet (struct net_device *dev)
{
struct netdev_private *np = (struct netdev_private *) dev->priv;
int entry = np->cur_rx % RX_RING_SIZE;
int cnt = np->old_rx + RX_RING_SIZE - np->cur_rx;
int rx_shift;
int cnt = 30;
spin_lock (&np->rx_lock);
if (np->old_rx > RX_RING_SIZE) {
rx_shift = RX_RING_SIZE;
np->old_rx -= rx_shift;
np->cur_rx -= rx_shift;
}
DEBUG_RFD_DUMP (np, 1);
/* If RFDDone, FrameStart and FrameEnd set, there is a new packet in. */
while (1) {
struct netdev_desc *desc = &np->rx_ring[entry];
......@@ -852,20 +840,19 @@ receive_packet (struct net_device *dev)
frame_status = le64_to_cpu (desc->status);
if (--cnt < 0)
break;
DEBUG_PKT_DUMP (np, pkt_len);
pci_dma_sync_single (np->pdev, desc->fraginfo, np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
/* Update rx error statistics, drop packet. */
if (frame_status & 0x003f0000) {
if (frame_status & RFS_Errors) {
np->stats.rx_errors++;
if (frame_status & 0x00300000)
if (frame_status & (RxRuntFrame | RxLengthError))
np->stats.rx_length_errors++;
if (frame_status & 0x00010000)
np->stats.rx_fifo_errors++;
if (frame_status & 0x00060000)
np->stats.rx_frame_errors++;
if (frame_status & 0x00080000)
if (frame_status & RxFCSError)
np->stats.rx_crc_errors++;
if (frame_status & RxAlignmentError && np->speed != 1000)
np->stats.rx_frame_errors++;
if (frame_status & RxFIFOOverrun)
np->stats.rx_fifo_errors++;
} else {
struct sk_buff *skb;
......@@ -893,17 +880,17 @@ receive_packet (struct net_device *dev)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
#endif
netif_rx (skb);
dev->last_rx = jiffies;
}
entry = (++np->cur_rx) % RX_RING_SIZE;
entry = (entry + 1) % RX_RING_SIZE;
}
spin_lock(&np->rx_lock);
np->cur_rx = entry;
/* Re-allocate skbuffs to fill the descriptor ring */
for (; np->cur_rx - np->old_rx > 0; np->old_rx++) {
entry = np->old_rx;
while (entry != np->cur_rx) {
struct sk_buff *skb;
entry = np->old_rx % RX_RING_SIZE;
/* Dropped packets don't need to re-allocate */
if (np->rx_skbuff[entry] == NULL) {
skb = dev_alloc_skb (np->rx_buf_sz);
......@@ -927,11 +914,9 @@ receive_packet (struct net_device *dev)
np->rx_ring[entry].fraginfo |=
cpu_to_le64 (np->rx_buf_sz) << 48;
np->rx_ring[entry].status = 0;
/* RxDMAPollNow */
writel (readl (dev->base_addr + DMACtrl) | 0x00000010,
dev->base_addr + DMACtrl);
entry = (entry + 1) % RX_RING_SIZE;
}
DEBUG_RFD_DUMP (np, 2);
np->old_rx = entry;
spin_unlock(&np->rx_lock);
return 0;
}
......@@ -943,14 +928,6 @@ rio_error (struct net_device *dev, int int_status)
struct netdev_private *np = dev->priv;
u16 macctrl;
/* Stop the down counter and recovery the interrupt */
if (int_status & IntRequested) {
writew (0, ioaddr + IntEnable);
writel (0, ioaddr + CountDown);
/* Enable default interrupts */
EnableInt ();
}
/* Link change event */
if (int_status & LinkEvent) {
if (mii_wait_link (dev, 10) == 0) {
......@@ -960,14 +937,19 @@ rio_error (struct net_device *dev, int int_status)
else
mii_get_media (dev);
macctrl = 0;
macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
macctrl |= (np->full_duplex) ? DuplexSelect : 0;
macctrl |= (np->tx_flow) ?
TxFlowControlEnable : 0;
macctrl |= (np->rx_flow) ?
RxFlowControlEnable : 0;
writew(macctrl, ioaddr + MACCtrl);
np->link_status = 1;
netif_carrier_on(dev);
} else {
printk (KERN_INFO "%s: Link off\n", dev->name);
np->link_status = 0;
netif_carrier_off(dev);
}
}
......@@ -991,41 +973,100 @@ get_stats (struct net_device *dev)
{
long ioaddr = dev->base_addr;
struct netdev_private *np = dev->priv;
u16 temp1;
u16 temp2;
int i;
unsigned int stat_reg;
/* All statistics registers need to be acknowledged,
else statistic overflow could cause problems */
np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
np->stats.tx_bytes += readl (ioaddr + OctetXmtOk);
temp1 = readw (ioaddr + FrameLostRxError);
np->stats.rx_errors += temp1;
np->stats.rx_missed_errors += temp1;
np->stats.tx_dropped += readw (ioaddr + FramesAbortXSColls);
temp1 = readl (ioaddr + SingleColFrames) +
readl (ioaddr + MultiColFrames) + readl (ioaddr + LateCollisions);
temp2 = readw (ioaddr + CarrierSenseErrors);
np->stats.tx_carrier_errors += temp2;
np->stats.tx_errors += readw (ioaddr + FramesWEXDeferal) +
readl (ioaddr + FramesWDeferredXmt) + temp2;
/* detailed rx_error */
np->stats.rx_length_errors += readw (ioaddr + FrameTooLongErrors);
np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError);
np->stats.multicast = readl (ioaddr + McstFramesRcvdOk);
np->stats.collisions += readl (ioaddr + SingleColFrames)
+ readl (ioaddr + MultiColFrames);
/* detailed tx errors */
stat_reg = readw (ioaddr + FramesAbortXSColls);
np->stats.tx_aborted_errors += stat_reg;
np->stats.tx_errors += stat_reg;
stat_reg = readw (ioaddr + CarrierSenseErrors);
np->stats.tx_carrier_errors += stat_reg;
np->stats.tx_errors += stat_reg;
/* Clear all other statistic register. */
readw (ioaddr + InRangeLengthErrors);
readw (ioaddr + MacControlFramesXmtd);
readl (ioaddr + McstOctetXmtOk);
readw (ioaddr + BcstFramesXmtdOk);
readl (ioaddr + McstFramesXmtdOk);
readw (ioaddr + BcstFramesRcvdOk);
readw (ioaddr + MacControlFramesRcvd);
readw (ioaddr + FrameTooLongErrors);
readw (ioaddr + InRangeLengthErrors);
readw (ioaddr + FramesCheckSeqErrors);
readw (ioaddr + FramesLostRxErrors);
readl (ioaddr + McstOctetXmtOk);
readl (ioaddr + BcstOctetXmtOk);
readl (ioaddr + McstFramesXmtdOk);
readl (ioaddr + FramesWDeferredXmt);
readl (ioaddr + LateCollisions);
readw (ioaddr + BcstFramesXmtdOk);
readw (ioaddr + MacControlFramesXmtd);
readw (ioaddr + FramesWEXDeferal);
for (i = 0x100; i <= 0x150; i += 4)
readl (ioaddr + i);
readw (ioaddr + TxJumboFrames);
readw (ioaddr + RxJumboFrames);
readw (ioaddr + TCPCheckSumErrors);
readw (ioaddr + UDPCheckSumErrors);
readw (ioaddr + IPCheckSumErrors);
return &np->stats;
}
static int
clear_stats (struct net_device *dev)
{
long ioaddr = dev->base_addr;
int i;
/* All statistics registers need to be acknowledged,
else statistic overflow could cause problems */
readl (ioaddr + FramesRcvOk);
readl (ioaddr + FramesXmtOk);
readl (ioaddr + OctetRcvOk);
readl (ioaddr + OctetXmtOk);
readl (ioaddr + McstFramesRcvdOk);
readl (ioaddr + SingleColFrames);
readl (ioaddr + MultiColFrames);
readl (ioaddr + LateCollisions);
/* detailed rx errors */
readw (ioaddr + FrameTooLongErrors);
readw (ioaddr + InRangeLengthErrors);
readw (ioaddr + FramesCheckSeqErrors);
readw (ioaddr + FramesLostRxErrors);
/* detailed tx errors */
readw (ioaddr + FramesAbortXSColls);
readw (ioaddr + CarrierSenseErrors);
/* Clear all other statistic register. */
readl (ioaddr + McstOctetXmtOk);
readw (ioaddr + BcstFramesXmtdOk);
readl (ioaddr + McstFramesXmtdOk);
readw (ioaddr + BcstFramesRcvdOk);
readw (ioaddr + MacControlFramesRcvd);
readw (ioaddr + BcstFramesRcvOk);
readl (ioaddr + McstFramesRcvOk);
readl (ioaddr + BcstOctetRcvOk);
readl (ioaddr + McstOctetXmtOk);
readl (ioaddr + BcstOctetXmtOk);
readl (ioaddr + McstFramesXmtdOk);
readl (ioaddr + FramesWDeferredXmt);
readw (ioaddr + BcstFramesXmtdOk);
readw (ioaddr + MacControlFramesXmtd);
readw (ioaddr + FramesWEXDeferal);
for (i = 0x100; i <= 0x150; i += 4)
readl (ioaddr + i);
......@@ -1034,9 +1075,10 @@ get_stats (struct net_device *dev)
readw (ioaddr + TCPCheckSumErrors);
readw (ioaddr + UDPCheckSumErrors);
readw (ioaddr + IPCheckSumErrors);
return &np->stats;
return 0;
}
int
change_mtu (struct net_device *dev, int new_mtu)
{
......@@ -1111,51 +1153,35 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
int phy_addr;
struct netdev_private *np = dev->priv;
struct mii_data *miidata = (struct mii_data *) &rq->ifr_data;
#ifdef RIO_DEBUG
struct ioctl_data *iodata = (struct ioctl_data *) (rq->ifr_data);
#endif
u16 *data = (u16 *) & rq->ifr_data;
struct netdev_desc *desc;
int i;
phy_addr = np->phy_addr;
switch (cmd) {
case SIOCDEVPRIVATE:
#ifdef RIO_DEBUG
if (rio_ioctl_ext (dev, iodata) != 0)
return -EOPNOTSUPP;
break;
#else
return -EOPNOTSUPP;
#endif
case SIOCDEVPRIVATE + 1:
miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
break;
case SIOCDEVPRIVATE + 2:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);
break;
case SIOCDEVPRIVATE + 3:
np->rx_debug = (data[0] <= 7) ? data[0] : 0;
printk ("rx_debug = %d\n", np->rx_debug);
break;
case SIOCDEVPRIVATE + 4:
np->tx_debug = (data[0] <= 7) ? data[0] : 0;
printk ("tx_debug = %d\n", np->tx_debug);
break;
case SIOCDEVPRIVATE + 5:
np->tx_full = 1;
netif_stop_queue (dev);
break;
case SIOCDEVPRIVATE + 6:
np->tx_full = 0;
netif_wake_queue (dev);
break;
case SIOCDEVPRIVATE + 7:
printk
("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n",
np->tx_full, np->cur_tx, np->old_tx, np->cur_rx,
netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx,
np->old_rx);
break;
case SIOCDEVPRIVATE + 8:
......@@ -1163,7 +1189,8 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
for (i = 0; i < TX_RING_SIZE; i++) {
desc = &np->tx_ring[i];
printk
("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
i,
(u32) (np->tx_ring_dma + i * sizeof (*desc)),
(u32) desc->next_desc,
(u32) desc->status, (u32) (desc->fraginfo >> 32),
......@@ -1172,110 +1199,17 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
}
printk ("\n");
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
#ifdef RIO_DEBUG
int
rio_ioctl_ext (struct net_device *dev, struct ioctl_data *iodata)
{
struct netdev_private *np = dev->priv;
int phy_addr = np->phy_addr;
u32 hi, lo;
int i;
BMCR_t bmcr;
BMSR_t bmsr;
if (iodata == NULL)
goto invalid_cmd;
if (strcmp (iodata->signature, "rio") != 0)
goto invalid_cmd;
switch (iodata->cmd) {
case 0:
for (i = 0; i < TX_RING_SIZE; i++) {
hi = np->tx_ring[i].status >> 32;
lo = np->tx_ring[i].status;
printk ("TFC=%08x %08x \n", hi, lo);
}
break;
case 1:
for (i = 0; i < RX_RING_SIZE; i++) {
hi = np->rx_ring[i].status >> 32;
lo = np->rx_ring[i].status;
printk ("RFS=%08x %08x \n", hi, lo);
}
break;
case 2:
break;
case 3:
if (iodata->data != NULL)
np->tx_debug = iodata->data[0];
break;
case 4:
/* Soft reset PHY */
mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
bmcr.image = 0;
bmcr.bits.an_enable = 1;
bmcr.bits.reset = 1;
mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
break;
case 5:
mii_write (dev, phy_addr, MII_BMCR, 0x1940);
mdelay (10);
mii_write (dev, phy_addr, MII_BMCR, 0x1940);
mdelay (100); /* wait a certain time */
break;
case 6:
/* 5) Set media and Power Up */
bmcr.image = 0;
bmcr.bits.power_down = 1;
if (np->an_enable) {
bmcr.bits.an_enable = 1;
} else {
if (np->speed == 100) {
bmcr.bits.speed100 = 1;
bmcr.bits.speed1000 = 0;
printk ("Manual 100 Mbps, ");
} else if (np->speed == 10) {
bmcr.bits.speed100 = 0;
bmcr.bits.speed1000 = 0;
printk ("Manual 10 Mbps, ");
}
if (np->full_duplex) {
bmcr.bits.duplex_mode = 1;
printk ("Full duplex. \n");
} else {
bmcr.bits.duplex_mode = 0;
printk ("Half duplex.\n");
}
}
mii_write (dev, phy_addr, MII_BMCR, bmcr.image);
break;
case 7:
bmcr.image = mii_read (dev, phy_addr, MII_BMCR);
bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
printk ("BMCR=%x BMSR=%x LinkUp=%d\n",
bmcr.image, bmsr.image, bmsr.bits.link_status);
break;
default:
return -EOPNOTSUPP;
}
return 0;
invalid_cmd:
return -1;
}
#endif
#define EEP_READ 0x0200
#define EEP_BUSY 0x8000
/* Read the EEPROM word */
static int __devinit
int
read_eeprom (long ioaddr, int eep_addr)
{
int i = 1000;
......@@ -1441,10 +1375,11 @@ mii_get_media (struct net_device *dev)
printk (KERN_INFO "Auto 10 Mbps, Half duplex\n");
}
if (negotiate.bits.pause) {
np->tx_flow = 1;
np->rx_flow = 1;
np->tx_flow &= 1;
np->rx_flow &= 1;
} else if (negotiate.bits.asymmetric) {
np->rx_flow = 1;
np->tx_flow = 0;
np->rx_flow &= 1;
}
/* else tx_flow, rx_flow = user select */
} else {
......@@ -1593,10 +1528,11 @@ mii_get_media_pcs (struct net_device *dev)
np->full_duplex = 0;
}
if (negotiate.bits.pause) {
np->tx_flow = 1;
np->rx_flow = 1;
np->tx_flow &= 1;
np->rx_flow &= 1;
} else if (negotiate.bits.asymmetric) {
np->rx_flow = 1;
np->tx_flow = 0;
np->rx_flow &= 1;
}
/* else tx_flow, rx_flow = user select */
} else {
......
......@@ -119,13 +119,13 @@ enum dl2x_offsets {
McstOctetRcvOk = 0xac,
BcstOctetRcvOk = 0xb0,
FramesRcvOk = 0xb4,
McstFramesRcvOk = 0xb8,
BcstFramesRcvOk = 0xbe,
McstFramesRcvdOk = 0xb8,
BcstFramesRcvdOk = 0xbe,
MacControlFramesRcvd = 0xc6,
FrameTooLongErrors = 0xc8,
InRangeLengthErrors = 0xca,
FrameCheckSeqError = 0xcc,
FrameLostRxError = 0xce,
FramesCheckSeqErrors = 0xcc,
FramesLostRxErrors = 0xce,
OctetXmtOk = 0xd0,
McstOctetXmtOk = 0xd4,
BcstOctetXmtOk = 0xd8,
......@@ -264,6 +264,7 @@ enum RFS_bits {
FrameEnd = 0x40000000,
RFDDone = 0x80000000,
TCIShift = 32,
RFS_Errors = 0x003f0000,
};
#define MII_RESET_TIME_OUT 10000
......@@ -648,7 +649,7 @@ struct netdev_private {
dma_addr_t tx_ring_dma;
dma_addr_t rx_ring_dma;
struct pci_dev *pdev;
spinlock_t lock;
spinlock_t tx_lock;
spinlock_t rx_lock;
struct net_device_stats stats;
unsigned int rx_buf_sz; /* Based on MTU+slack. */
......@@ -657,7 +658,6 @@ struct netdev_private {
unsigned int chip_id; /* PCI table chip id */
unsigned int rx_coalesce; /* Maximum frames each RxDMAComplete intr */
unsigned int rx_timeout; /* Wait time between RxDMAComplete intr */
unsigned int tx_full:1; /* The Tx queue is full. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int an_enable:2; /* Auto-Negotiated Enable */
unsigned int jumbo:1; /* Jumbo frame enable */
......@@ -665,6 +665,7 @@ struct netdev_private {
unsigned int tx_flow:1; /* Tx flow control enable */
unsigned int rx_flow:1; /* Rx flow control enable */
unsigned int phy_media:1; /* 1: fiber, 0: copper */
unsigned int link_status:1; /* Current link status */
unsigned char pci_rev_id; /* PCI revision ID */
struct netdev_desc *last_tx; /* Last Tx descriptor used. */
unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */
......@@ -677,8 +678,6 @@ struct netdev_private {
u16 advertising; /* NWay media advertisement */
u16 negotiate; /* Negotiated media */
int phy_addr; /* PHY addresses. */
int tx_debug;
int rx_debug;
};
/* The station address location in the EEPROM. */
......@@ -707,114 +706,4 @@ MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
#define DEFAULT_RXT 750
#define DEFAULT_TXC 1
#define MAX_TXC 8
#ifdef RIO_DEBUG
#define DEBUG_TFD_DUMP(x) debug_tfd_dump(x)
#define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag)
#define DEBUG_PKT_DUMP(x,len) debug_pkt_dump(x,len)
#define DEBUG_PRINT printk
static inline void
debug_tfd_dump (struct netdev_private *np)
{
int i;
struct netdev_desc *desc;
if (np->tx_debug == 6) {
printk ("TFDone Dump: ");
for (i = 0; i < TX_RING_SIZE; i++) {
desc = &np->tx_ring[i];
if ((desc->fraginfo & 0xffffffffff) == 0)
printk ("X");
else
printk ("%d", (desc->status & TFDDone) ? 1 : 0);
}
printk ("\n");
}
if (np->tx_debug == 5) {
for (i = 0; i < TX_RING_SIZE; i++) {
desc = &np->tx_ring[i];
printk
("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
(u32) np->tx_ring_dma + i * sizeof (*desc),
(u32) desc->next_desc, (u32) desc->status,
(u32) (desc->fraginfo >> 32),
(u32) desc->fraginfo);
printk ("\n");
}
printk ("\n");
}
}
static inline void
debug_rfd_dump (struct netdev_private *np, int flag)
{
int i;
struct netdev_desc *desc;
int entry = np->cur_rx % RX_RING_SIZE;
if (np->rx_debug == 5) {
for (i = 0; i < RX_RING_SIZE; i++) {
desc = &np->rx_ring[i];
printk
("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
(u32) np->rx_ring_dma + i * sizeof (*desc),
(u32) desc->next_desc, (u32) desc->status,
(u32) (desc->fraginfo >> 32),
(u32) desc->fraginfo);
printk ("\n");
}
printk ("\n");
}
if (np->rx_debug == 6) {
if (flag == 1)
printk ("RFDone Dump: ");
else if (flag == 2)
printk ("Re-Filling: ");
for (i = 0; i < RX_RING_SIZE; i++) {
desc = &np->rx_ring[i];
printk ("%d", (desc->status & RFDDone) ? 1 : 0);
}
printk ("\n");
}
if (np->rx_debug == 7) {
printk (" In rcv_pkt(), entry %d status %4.4x %4.4x.\n",
entry, (u32) (np->rx_ring[entry].status >> 32),
(u32) np->rx_ring[entry].status);
}
}
static inline void
debug_pkt_dump (struct netdev_private *np, int pkt_len)
{
int entry = np->cur_rx % RX_RING_SIZE;
struct netdev_desc *desc = &np->rx_ring[entry];
u64 frame_status = le64_to_cpu (desc->status);
unsigned char *pchar;
unsigned char *phead;
int i;
if (np->rx_debug == 4) {
printk (" rcv_pkt: status was %4.4x %4.4x.\n",
(u32) (frame_status >> 32), (u32) frame_status);
}
if (np->rx_debug == 7) {
#error Please convert me to Documentation/DMA-mapping.txt
phead =
bus_to_virt (le64_to_cpu (desc->fraginfo & 0xffffffffff));
for (pchar = phead, i = 0; i < pkt_len; i++, pchar++) {
printk ("%02x ", *pchar);
if ((i + 1) % 20 == 0)
printk ("\n");
}
}
}
#else
#define DEBUG_TFD_DUMP(x) {}
#define DEBUG_RFD_DUMP(x,flag) {}
#define DEBUG_PKT_DUMP(x,len) {}
#define DEBUG_PRINT() {}
#endif
#endif /* __DL2K_H__ */
......@@ -503,6 +503,7 @@ enum led_state_e {
#define IS_BACHELOR 0x00000010 /* set if 82558 or newer board */
#define IS_ICH 0x00000020
#define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */
#define LED_IS_ON 0x00000080 /* LED is turned ON by the driver */
typedef struct net_device_stats net_dev_stats_t;
......@@ -909,7 +910,6 @@ struct ethtool_lpbk_data{
};
#endif
struct e100_private {
u32 flags; /* board management flags */
u32 tx_per_underrun; /* number of good tx frames per underrun */
......@@ -999,7 +999,10 @@ struct e100_private {
u16 ip_lbytes;
#endif
#ifdef ETHTOOL_TEST
struct ethtool_lpbk_data loopback;
struct ethtool_lpbk_data loopback;
#endif
#ifdef ETHTOOL_PHYS_ID
struct timer_list blink_timer; /* led blink timer id */
#endif
#ifdef CONFIG_PM
......
......@@ -593,7 +593,6 @@ e100_config_wol(struct e100_private *bdp)
}
#endif
#ifdef ETHTOOL_TEST
/**
* e100_config_loopback_mode
* @bdp: atapter's private data struct
......@@ -690,5 +689,4 @@ e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
return bc_changed;
}
#endif
......@@ -163,6 +163,9 @@ static char *test_strings[] = {
"E100_LPBK_PHY_FAIL"
};
#endif
#ifdef ETHTOOL_PHYS_ID
static int e100_ethtool_led_blink(struct net_device *, struct ifreq *);
#endif
#endif /*E100_ETHTOOL_IOCTL */
......@@ -182,7 +185,7 @@ static void e100_non_tx_background(unsigned long);
/* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation";
#define E100_VERSION "2.0.27-pre3"
#define E100_VERSION "2.0.30-k1"
#define E100_FULL_DRIVER_NAME "Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver "
......@@ -691,9 +694,10 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
#ifdef ETHTOOL_GWOL
/* Disabling all WOLs as initialization */
bdp->wolsupported = bdp->wolopts = 0;
if (bdp->rev_id >= D101MA_REV_ID) {
bdp->wolsupported =
WAKE_PHY | WAKE_UCAST | WAKE_ARP | WAKE_MAGIC;
if (bdp->rev_id >= D101A4_REV_ID) {
bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
if (bdp->rev_id >= D101MA_REV_ID)
bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
bdp->wolopts = WAKE_MAGIC;
}
#endif
......@@ -3334,6 +3338,11 @@ e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
case ETHTOOL_GSTRINGS:
rc = e100_ethtool_gstrings(dev,ifr);
break;
#endif
#ifdef ETHTOOL_PHYS_ID
case ETHTOOL_PHYS_ID:
rc = e100_ethtool_led_blink(dev,ifr);
break;
#endif
default:
break;
......@@ -3641,6 +3650,94 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr)
}
#endif
#ifdef ETHTOOL_PHYS_ID
#define E100_BLINK_INTERVAL (HZ/4)
/**
* e100_led_control
* @bdp: atapter's private data struct
* @led_mdi_op: led operation
*
* Software control over adapter's led. The possible operations are:
* TURN LED OFF, TURN LED ON and RETURN LED CONTROL TO HARDWARE.
*/
static void
e100_led_control(struct e100_private *bdp, u16 led_mdi_op)
{
spin_lock_bh(&bdp->mdi_access_lock);
e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL,
bdp->phy_addr, led_mdi_op);
spin_unlock_bh(&bdp->mdi_access_lock);
}
/**
* e100_led_blink_callback
* @data: pointer to atapter's private data struct
*
* Blink timer callback function. Toggles ON/OFF led status bit and calls
* led hardware access function.
*/
static void
e100_led_blink_callback(unsigned long data)
{
struct e100_private *bdp = (struct e100_private *) data;
if(bdp->flags & LED_IS_ON) {
bdp->flags &= ~LED_IS_ON;
e100_led_control(bdp, PHY_82555_LED_OFF);
} else {
bdp->flags |= LED_IS_ON;
if (bdp->rev_id >= D101MA_REV_ID)
e100_led_control(bdp, PHY_82555_LED_ON_559);
else
e100_led_control(bdp, PHY_82555_LED_ON_PRE_559);
}
mod_timer(&bdp->blink_timer, jiffies + E100_BLINK_INTERVAL);
}
/**
* e100_ethtool_led_blink
* @dev: pointer to atapter's net_device struct
* @ifr: pointer to ioctl request structure
*
* Blink led ioctl handler. Initialtes blink timer and sleeps until
* blink period expires. Than it kills timer and returns. The led control
* is returned back to hardware when blink timer is killed.
*/
static int
e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr)
{
struct e100_private *bdp;
struct ethtool_value ecmd;
bdp = dev->priv;
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
return -EFAULT;
if(!bdp->blink_timer.function) {
init_timer(&bdp->blink_timer);
bdp->blink_timer.function = e100_led_blink_callback;
bdp->blink_timer.data = (unsigned long) bdp;
}
mod_timer(&bdp->blink_timer, jiffies);
set_current_state(TASK_INTERRUPTIBLE);
if ((!ecmd.data) || (ecmd.data > MAX_SCHEDULE_TIMEOUT / HZ))
ecmd.data = MAX_SCHEDULE_TIMEOUT / HZ;
schedule_timeout(ecmd.data * HZ);
del_timer_sync(&bdp->blink_timer);
e100_led_control(bdp, PHY_82555_LED_NORMAL_CONTROL);
return 0;
}
#endif
static inline int __devinit
e100_10BaseT_adapter(struct e100_private *bdp)
{
......
......@@ -548,7 +548,7 @@ read_bundle_max_def(char *page, char **start, off_t off,
int len;
len = read_int_param(page, "CPU Saver Maximum Bundle",
"Sets the value for CPU saver's maximum value",
"Sets CPU saver's maximum value",
E100_DEFAULT_CPUSAVER_BUNDLE_MAX, 0x1, 0xFFFF);
return generic_read(page, start, off, count, eof, len);
......
......@@ -69,6 +69,7 @@ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "e100.h"
#include "e100_config.h"
#ifdef ETHTOOL_TEST
......@@ -458,10 +459,3 @@ e100_diag_loopback_free (struct e100_private *bdp)
#endif
################################################################################
#
# This software program is available to you under a choice of one of two
# licenses. You may choose to be licensed under either the GNU General Public
# License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
# or the Intel BSD + Patent License, the text of which follows:
#
# Recipient has requested a license and Intel Corporation ("Intel") is willing
# to grant a license for the software entitled Linux Base Driver for the
# Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
# by Intel Corporation. The following definitions apply to this license:
#
# "Licensed Patents" means patent claims licensable by Intel Corporation which
# are necessarily infringed by the use of sale of the Software alone or when
# combined with the operating system referred to below.
#
# "Recipient" means the party to whom Intel delivers this Software.
#
# "Licensee" means Recipient and those third parties that receive a license to
# any operating system available under the GNU General Public License 2.0 or
# later.
#
# Copyright (c) 1999 - 2002 Intel Corporation.
# All rights reserved.
#
# The license is provided to Recipient and Recipient's Licensees under the
# following terms.
#
# Redistribution and use in source and binary forms of the Software, with or
# without modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code of the Software may retain the above
# copyright notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form of the Software may reproduce the above
# copyright notice, this list of conditions and the following disclaimer in
# the documentation and/or materials provided with the distribution.
#
# Neither the name of Intel Corporation nor the names of its contributors
# shall be used to endorse or promote products derived from this Software
# without specific prior written permission.
#
# Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
# royalty-free patent license under Licensed Patents to make, use, sell, offer
# to sell, import and otherwise transfer the Software, if any, in source code
# and object code form. This license shall include changes to the Software
# that are error corrections or other minor changes to the Software that do
# not add functionality or features when the Software is incorporated in any
# version of an operating system that has been distributed under the GNU
# General Public License 2.0 or later. This patent license shall apply to the
# combination of the Software and any operating system licensed under the GNU
# General Public License 2.0 or later if, at the time Intel provides the
# Software to Recipient, such addition of the Software to the then publicly
# available versions of such operating systems available under the GNU General
# Public License 2.0 or later (whether in gold, beta or alpha form) causes
# such combination to be covered by the Licensed Patents. The patent license
# shall not apply to any other combinations which include the Software. NO
# hardware per se is licensed hereunder.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
################################################################################
#
# Makefile for the Intel(R) PRO/1000 ethernet driver
#
......
......@@ -107,18 +107,21 @@
#include <linux/udp.h>
#include <net/pkt_sched.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/reboot.h>
#include <linux/ethtool.h>
#ifdef NETIF_F_HW_VLAN_TX
#include <linux/if_vlan.h>
#endif
#define BAR_0 0
#define PCI_DMA_64BIT 0xffffffffffffffffULL
#define PCI_DMA_32BIT 0x00000000ffffffffULL
struct e1000_adapter;
#include "e1000_hw.h"
#define BAR_0 0
#if DBG
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
#else
......@@ -156,6 +159,7 @@ struct e1000_buffer {
struct sk_buff *skb;
uint64_t dma;
unsigned long length;
unsigned long time_stamp;
};
struct e1000_desc_ring {
......@@ -204,10 +208,13 @@ struct e1000_adapter {
spinlock_t stats_lock;
atomic_t irq_sem;
#ifdef ETHTOOL_PHYS_ID
struct timer_list blink_timer;
unsigned long led_status;
#endif
/* TX */
struct e1000_desc_ring tx_ring;
unsigned long trans_finish;
spinlock_t tx_lock;
uint32_t txd_cmd;
int max_data_per_txd;
......@@ -228,6 +235,9 @@ struct e1000_adapter {
struct e1000_hw_stats stats;
struct e1000_phy_info phy_info;
struct e1000_phy_stats phy_stats;
};
uint32_t pci_state[16];
};
#endif /* _E1000_H_ */
......@@ -75,7 +75,6 @@
#include "e1000.h"
#include <linux/ethtool.h>
#include <asm/uaccess.h>
extern char e1000_driver_name[];
......@@ -83,7 +82,6 @@ extern char e1000_driver_version[];
extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_enable_WOL(struct e1000_adapter *adapter);
static void
e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
......@@ -128,6 +126,10 @@ e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
SUPPORTED_Autoneg);
ecmd->port = PORT_FIBRE;
if(hw->mac_type >= e1000_82545)
ecmd->transceiver = XCVR_INTERNAL;
else
ecmd->transceiver = XCVR_EXTERNAL;
}
......@@ -211,9 +213,37 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
strncpy(drvinfo->version, e1000_driver_version, 32);
strncpy(drvinfo->fw_version, "", 32);
strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
#define E1000_REGS_LEN 32
drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t);
drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw);
}
static void
e1000_ethtool_gregs(struct e1000_adapter *adapter,
struct ethtool_regs *regs, uint32_t *regs_buff)
{
struct e1000_hw *hw = &adapter->hw;
regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
regs_buff[0] = E1000_READ_REG(hw, CTRL);
regs_buff[1] = E1000_READ_REG(hw, STATUS);
regs_buff[2] = E1000_READ_REG(hw, RCTL);
regs_buff[3] = E1000_READ_REG(hw, RDLEN);
regs_buff[4] = E1000_READ_REG(hw, RDH);
regs_buff[5] = E1000_READ_REG(hw, RDT);
regs_buff[6] = E1000_READ_REG(hw, RDTR);
regs_buff[7] = E1000_READ_REG(hw, TCTL);
regs_buff[8] = E1000_READ_REG(hw, TDLEN);
regs_buff[9] = E1000_READ_REG(hw, TDH);
regs_buff[10] = E1000_READ_REG(hw, TDT);
regs_buff[11] = E1000_READ_REG(hw, TIDV);
return;
}
static void
e1000_ethtool_geeprom(struct e1000_adapter *adapter,
struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
......@@ -228,7 +258,7 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
if ((eeprom->offset + eeprom->len) > max_len)
eeprom->len = (max_len - eeprom->offset);
for(i = 0; i < max_len; i++)
for(i = 0; i < (max_len >> 1); i++)
e1000_read_eeprom(&adapter->hw, i, &eeprom_buff[i]);
}
......@@ -237,12 +267,33 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
{
struct e1000_hw *hw = &adapter->hw;
if(hw->mac_type < e1000_82544) {
switch(adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
case E1000_DEV_ID_82544EI_FIBER:
default:
wol->supported = 0;
wol->wolopts = 0;
return;
}
case E1000_DEV_ID_82546EB_FIBER:
/* Wake events only supported on port A for dual fiber */
if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
wol->wolopts = 0;
return;
}
/* Fall Through */
case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER:
wol->supported = WAKE_PHY | WAKE_UCAST |
WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
......@@ -257,6 +308,8 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
wol->wolopts |= WAKE_BCAST;
if(adapter->wol & E1000_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
}
}
static int
......@@ -264,8 +317,30 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
{
struct e1000_hw *hw = &adapter->hw;
if(hw->mac_type < e1000_82544)
switch(adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
case E1000_DEV_ID_82544EI_FIBER:
default:
return wol->wolopts ? -EOPNOTSUPP : 0;
case E1000_DEV_ID_82546EB_FIBER:
/* Wake events only supported on port A for dual fiber */
if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
return wol->wolopts ? -EOPNOTSUPP : 0;
/* Fall Through */
case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER:
if(wol->wolopts & WAKE_ARP)
return -EOPNOTSUPP;
adapter->wol = 0;
......@@ -279,10 +354,58 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
adapter->wol |= E1000_WUFC_BC;
if(wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
}
return 0;
}
#ifdef ETHTOOL_PHYS_ID
/* toggle LED 4 times per second = 2 "blinks" per second */
#define E1000_ID_INTERVAL (HZ/4)
/* bit defines for adapter->led_status */
#define E1000_LED_ON 0
static void
e1000_led_blink_callback(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
e1000_led_off(&adapter->hw);
else
e1000_led_on(&adapter->hw);
mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
}
static int
e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
{
if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
adapter->blink_timer.data = (unsigned long) adapter;
}
e1000_setup_led(&adapter->hw);
mod_timer(&adapter->blink_timer, jiffies);
set_current_state(TASK_INTERRUPTIBLE);
if(id->data)
schedule_timeout(id->data * HZ);
else
schedule_timeout(MAX_SCHEDULE_TIMEOUT);
del_timer_sync(&adapter->blink_timer);
e1000_led_off(&adapter->hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
e1000_cleanup_led(&adapter->hw);
e1000_enable_WOL(adapter);
return 0;
}
#endif /* ETHTOOL_PHYS_ID */
int
e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
......@@ -317,6 +440,22 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
return -EFAULT;
return 0;
}
case ETHTOOL_GREGS: {
struct ethtool_regs regs = {ETHTOOL_GREGS};
uint32_t regs_buff[E1000_REGS_LEN];
if(copy_from_user(&regs, addr, sizeof(regs)))
return -EFAULT;
e1000_ethtool_gregs(adapter, &regs, regs_buff);
if(copy_to_user(addr, &regs, sizeof(regs)))
return -EFAULT;
addr += offsetof(struct ethtool_regs, data);
if(copy_to_user(addr, regs_buff, regs.len))
return -EFAULT;
return 0;
}
case ETHTOOL_NWAY_RST: {
if(!capable(CAP_NET_ADMIN))
return -EPERM;
......@@ -324,6 +463,14 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
e1000_up(adapter);
return 0;
}
#ifdef ETHTOOL_PHYS_ID
case ETHTOOL_PHYS_ID: {
struct ethtool_value id;
if(copy_from_user(&id, addr, sizeof(id)))
return -EFAULT;
return e1000_ethtool_led_blink(adapter, &id);
}
#endif /* ETHTOOL_PHYS_ID */
case ETHTOOL_GLINK: {
struct ethtool_value link = {ETHTOOL_GLINK};
link.data = netif_carrier_ok(netdev);
......
......@@ -93,6 +93,7 @@ static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t
static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw);
static void e1000_setup_eeprom(struct e1000_hw *hw);
static void e1000_standby_eeprom(struct e1000_hw *hw);
static int32_t e1000_id_led_init(struct e1000_hw * hw);
/******************************************************************************
* Reset the transmit and receive units; mask and clear all interrupts.
......@@ -197,9 +198,20 @@ e1000_init_hw(struct e1000_hw *hw)
uint32_t i;
int32_t ret_val;
uint16_t pci_cmd_word;
uint16_t pcix_cmd_word;
uint16_t pcix_stat_hi_word;
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
DEBUGFUNC("e1000_init_hw");
/* Initialize Identification LED */
ret_val = e1000_id_led_init(hw);
if(ret_val < 0) {
DEBUGOUT("Error Initializing Identification LED\n");
return ret_val;
}
/* Set the Media Type and exit with error if it is not valid. */
if(hw->mac_type != e1000_82543) {
/* tbi_compatibility is only valid on 82543 */
......@@ -264,6 +276,21 @@ e1000_init_hw(struct e1000_hw *hw)
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
}
/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
if(hw->bus_type == e1000_bus_type_pcix) {
e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word);
e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >>
PCIX_COMMAND_MMRBC_SHIFT;
stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
PCIX_STATUS_HI_MMRBC_SHIFT;
if(cmd_mmrbc > stat_mmrbc) {
pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word);
}
}
/* Call a subroutine to configure the link and setup flow control. */
ret_val = e1000_setup_link(hw);
......@@ -541,6 +568,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
*/
if(hw->mac_type > e1000_82543) {
ctrl |= E1000_CTRL_SLU;
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, CTRL, ctrl);
} else {
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
......@@ -2061,6 +2089,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
break;
case e1000_82540:
case e1000_82545:
case e1000_82546:
if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
break;
default:
......@@ -2087,9 +2117,9 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
DEBUGFUNC("e1000_phy_reset_dsp");
do {
if(e1000_write_phy_reg(hw, 29, 0x1d) < 0) break;
if(e1000_write_phy_reg(hw, 30, 0xc1) < 0) break;
if(e1000_write_phy_reg(hw, 30, 0x00) < 0) break;
if(e1000_write_phy_reg(hw, 29, 0x001d) < 0) break;
if(e1000_write_phy_reg(hw, 30, 0x00c1) < 0) break;
if(e1000_write_phy_reg(hw, 30, 0x0000) < 0) break;
ret_val = 0;
} while(0);
......@@ -2521,6 +2551,13 @@ e1000_read_mac_addr(struct e1000_hw * hw)
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
}
if((hw->mac_type == e1000_82546) &&
(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
if(hw->perm_mac_addr[5] & 0x01)
hw->perm_mac_addr[5] &= ~(0x01);
else
hw->perm_mac_addr[5] |= 0x01;
}
for(i = 0; i < NODE_ADDRESS_SIZE; i++)
hw->mac_addr[i] = hw->perm_mac_addr[i];
return 0;
......@@ -2785,6 +2822,74 @@ e1000_clear_vfta(struct e1000_hw *hw)
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
}
static int32_t
e1000_id_led_init(struct e1000_hw * hw)
{
uint32_t ledctl;
const uint32_t ledctl_mask = 0x000000FF;
const uint32_t ledctl_on = E1000_LEDCTL_MODE_LED_ON;
const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
uint16_t eeprom_data, i, temp;
const uint16_t led_mask = 0x0F;
DEBUGFUNC("e1000_id_led_init");
if(hw->mac_type < e1000_82540) {
/* Nothing to do */
return 0;
}
ledctl = E1000_READ_REG(hw, LEDCTL);
hw->ledctl_default = ledctl;
hw->ledctl_mode1 = hw->ledctl_default;
hw->ledctl_mode2 = hw->ledctl_default;
if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
if((eeprom_data== ID_LED_RESERVED_0000) ||
(eeprom_data == ID_LED_RESERVED_FFFF)) eeprom_data = ID_LED_DEFAULT;
for(i = 0; i < 4; i++) {
temp = (eeprom_data >> (i << 2)) & led_mask;
switch(temp) {
case ID_LED_ON1_DEF2:
case ID_LED_ON1_ON2:
case ID_LED_ON1_OFF2:
hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
hw->ledctl_mode1 |= ledctl_on << (i << 3);
break;
case ID_LED_OFF1_DEF2:
case ID_LED_OFF1_ON2:
case ID_LED_OFF1_OFF2:
hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
hw->ledctl_mode1 |= ledctl_off << (i << 3);
break;
default:
/* Do nothing */
break;
}
switch(temp) {
case ID_LED_DEF1_ON2:
case ID_LED_ON1_ON2:
case ID_LED_OFF1_ON2:
hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
hw->ledctl_mode2 |= ledctl_on << (i << 3);
break;
case ID_LED_DEF1_OFF2:
case ID_LED_ON1_OFF2:
case ID_LED_OFF1_OFF2:
hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
hw->ledctl_mode2 |= ledctl_off << (i << 3);
break;
default:
/* Do nothing */
break;
}
}
return 0;
}
/******************************************************************************
* Prepares SW controlable LED for use and saves the current state of the LED.
*
......@@ -2807,22 +2912,24 @@ e1000_setup_led(struct e1000_hw *hw)
case E1000_DEV_ID_82544GC_LOM:
/* No setup necessary */
break;
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_FIBER:
ledctl = E1000_READ_REG(hw, LEDCTL);
/* Save current LEDCTL settings */
hw->ledctl = ledctl;
/* Turn off LED2 and LED3 */
ledctl &= ~(E1000_LEDCTL_LED2_IVRT |
E1000_LEDCTL_LED2_BLINK |
E1000_LEDCTL_LED2_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED2_MODE_SHIFT);
ledctl &= ~(E1000_LEDCTL_LED3_IVRT |
E1000_LEDCTL_LED3_BLINK |
E1000_LEDCTL_LED3_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED3_MODE_SHIFT);
hw->ledctl_default = ledctl;
/* Turn off LED0 */
ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
E1000_LEDCTL_LED0_BLINK |
E1000_LEDCTL_LED0_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT);
E1000_WRITE_REG(hw, LEDCTL, ledctl);
break;
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
break;
default:
DEBUGOUT("Invalid device ID\n");
return -E1000_ERR_CONFIG;
......@@ -2852,8 +2959,12 @@ e1000_cleanup_led(struct e1000_hw *hw)
break;
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER:
/* Restore LEDCTL settings */
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl);
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
break;
default:
DEBUGOUT("Invalid device ID\n");
......@@ -2871,7 +2982,6 @@ int32_t
e1000_led_on(struct e1000_hw *hw)
{
uint32_t ctrl;
uint32_t ledctl;
DEBUGFUNC("e1000_led_on");
......@@ -2889,6 +2999,8 @@ e1000_led_on(struct e1000_hw *hw)
case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_FIBER:
ctrl = E1000_READ_REG(hw, CTRL);
/* Clear SW Defineable Pin 0 to turn on the LED */
ctrl &= ~E1000_CTRL_SWDPIN0;
......@@ -2897,11 +3009,9 @@ e1000_led_on(struct e1000_hw *hw)
break;
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
ledctl = E1000_READ_REG(hw, LEDCTL);
/* Set LED 3 mode to on */
ledctl &= ~E1000_LEDCTL_LED3_MODE_MASK;
ledctl |= (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED3_MODE_SHIFT);
E1000_WRITE_REG(hw, LEDCTL, ledctl);
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
break;
default:
DEBUGOUT("Invalid device ID\n");
......@@ -2919,7 +3029,6 @@ int32_t
e1000_led_off(struct e1000_hw *hw)
{
uint32_t ctrl;
uint32_t ledctl;
DEBUGFUNC("e1000_led_off");
......@@ -2937,6 +3046,8 @@ e1000_led_off(struct e1000_hw *hw)
case E1000_DEV_ID_82544EI_COPPER:
case E1000_DEV_ID_82544GC_COPPER:
case E1000_DEV_ID_82544GC_LOM:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_FIBER:
ctrl = E1000_READ_REG(hw, CTRL);
/* Set SW Defineable Pin 0 to turn off the LED */
ctrl |= E1000_CTRL_SWDPIN0;
......@@ -2945,11 +3056,9 @@ e1000_led_off(struct e1000_hw *hw)
break;
case E1000_DEV_ID_82540EM:
case E1000_DEV_ID_82540EM_LOM:
ledctl = E1000_READ_REG(hw, LEDCTL);
/* Set LED 3 mode to off */
ledctl &= ~E1000_LEDCTL_LED3_MODE_MASK;
ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED3_MODE_SHIFT);
E1000_WRITE_REG(hw, LEDCTL, ledctl);
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
break;
default:
DEBUGOUT("Invalid device ID\n");
......
......@@ -92,6 +92,8 @@ typedef enum {
e1000_82543,
e1000_82544,
e1000_82540,
e1000_82545,
e1000_82546,
e1000_num_macs
} e1000_mac_type;
......@@ -260,6 +262,7 @@ void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
void e1000_get_bus_info(struct e1000_hw *hw);
void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
/* PCI Device IDs */
......@@ -272,7 +275,11 @@ void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
#define E1000_DEV_ID_82544GC_LOM 0x100D
#define E1000_DEV_ID_82540EM 0x100E
#define E1000_DEV_ID_82540EM_LOM 0x1015
#define NUM_DEV_IDS 9
#define E1000_DEV_ID_82545EM_COPPER 0x100F
#define E1000_DEV_ID_82545EM_FIBER 0x1011
#define E1000_DEV_ID_82546EB_COPPER 0x1010
#define E1000_DEV_ID_82546EB_FIBER 0x1012
#define NUM_DEV_IDS 13
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
......@@ -882,7 +889,9 @@ struct e1000_hw {
uint32_t num_mc_addrs;
uint32_t collision_delta;
uint32_t tx_packet_delta;
uint32_t ledctl;
uint32_t ledctl_default;
uint32_t ledctl_mode1;
uint32_t ledctl_mode2;
uint16_t autoneg_advertised;
uint16_t pci_cmd_word;
uint16_t fc_high_water;
......@@ -1324,11 +1333,29 @@ struct e1000_hw {
#define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */
/* EEPROM Word Offsets */
#define EEPROM_ID_LED_SETTINGS 0x0004
#define EEPROM_INIT_CONTROL1_REG 0x000A
#define EEPROM_INIT_CONTROL2_REG 0x000F
#define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F
/* Word definitions for ID LED Settings */
#define ID_LED_RESERVED_0000 0x0000
#define ID_LED_RESERVED_FFFF 0xFFFF
#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \
(ID_LED_OFF1_OFF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_DEF1_DEF2))
#define ID_LED_DEF1_DEF2 0x1
#define ID_LED_DEF1_ON2 0x2
#define ID_LED_DEF1_OFF2 0x3
#define ID_LED_ON1_DEF2 0x4
#define ID_LED_ON1_ON2 0x5
#define ID_LED_ON1_OFF2 0x6
#define ID_LED_OFF1_DEF2 0x7
#define ID_LED_OFF1_ON2 0x8
#define ID_LED_OFF1_OFF2 0x9
/* Mask bits for fields in Word 0x0a of the EEPROM */
#define EEPROM_WORD0A_ILOS 0x0010
#define EEPROM_WORD0A_SWDPIO 0x01E0
......@@ -1414,6 +1441,16 @@ struct e1000_hw {
#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */
#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */
/* PCIX Config space */
#define PCIX_COMMAND_REGISTER 0xE6
#define PCIX_STATUS_REGISTER_LO 0xE8
#define PCIX_STATUS_REGISTER_HI 0xEA
#define PCIX_COMMAND_MMRBC_MASK 0x000C
#define PCIX_COMMAND_MMRBC_SHIFT 0x2
#define PCIX_STATUS_HI_MMRBC_MASK 0x0060
#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5
/* The number of bits that we need to shift right to move the "pause"
* bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field
......
......@@ -76,7 +76,7 @@
char e1000_driver_name[] = "e1000";
char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
char e1000_driver_version[] = "4.2.8";
char e1000_driver_version[] = "4.2.17-k1";
char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
......@@ -114,6 +114,10 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
{0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */
{0,}
};
......@@ -126,7 +130,7 @@ static char *e1000_strings[] = {
"IBM Mobile, Desktop & Server Adapters"
};
/* e1000_main.c Function Prototypes */
/* Local Function Prototypes */
int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter);
......@@ -169,13 +173,24 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
struct e1000_rx_desc *rx_desc,
struct sk_buff *skb);
void e1000_enable_WOL(struct e1000_adapter *adapter);
#ifdef NETIF_F_HW_VLAN_TX
static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
#endif
static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
static int e1000_suspend(struct pci_dev *pdev, uint32_t state);
#ifdef CONFIG_PM
static int e1000_resume(struct pci_dev *pdev);
#endif
struct notifier_block e1000_notifier = {
notifier_call: e1000_notify_reboot,
next: NULL,
priority: 0
};
/* Exported from other modules */
extern void e1000_check_options(struct e1000_adapter *adapter);
......@@ -189,8 +204,10 @@ static struct pci_driver e1000_driver = {
probe: e1000_probe,
remove: __devexit_p(e1000_remove),
/* Power Managment Hooks */
suspend: NULL,
resume: NULL
#ifdef CONFIG_PM
suspend: e1000_suspend,
resume: e1000_resume
#endif
};
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
......@@ -207,12 +224,16 @@ MODULE_LICENSE("Dual BSD/GPL");
static int __init
e1000_init_module(void)
{
int ret;
printk(KERN_INFO "%s - version %s\n",
e1000_driver_string, e1000_driver_version);
printk(KERN_INFO "%s\n", e1000_copyright);
return pci_module_init(&e1000_driver);
ret = pci_module_init(&e1000_driver);
if(ret >= 0)
register_reboot_notifier(&e1000_notifier);
return ret;
}
module_init(e1000_init_module);
......@@ -227,6 +248,7 @@ module_init(e1000_init_module);
static void __exit
e1000_exit_module(void)
{
unregister_reboot_notifier(&e1000_notifier);
pci_unregister_driver(&e1000_driver);
}
......@@ -290,11 +312,11 @@ e1000_reset(struct e1000_adapter *adapter)
adapter->hw.fc = adapter->hw.original_fc;
e1000_reset_hw(&adapter->hw);
if(adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
e1000_init_hw(&adapter->hw);
e1000_reset_adaptive(&adapter->hw);
e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
e1000_enable_WOL(adapter);
}
/**
......@@ -324,10 +346,10 @@ e1000_probe(struct pci_dev *pdev,
if((i = pci_enable_device(pdev)))
return i;
if(!(i = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff))) {
if(!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) {
pci_using_dac = 1;
} else {
if((i = pci_set_dma_mask(pdev, (u64) 0xffffffff))) {
if((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) {
E1000_ERR("No usable DMA configuration, aborting\n");
return i;
}
......@@ -403,8 +425,10 @@ e1000_probe(struct pci_dev *pdev,
/* make sure the EEPROM is good */
if(e1000_validate_eeprom_checksum(&adapter->hw) < 0)
if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
goto err_eeprom;
}
/* copy the MAC address out of the EEPROM */
......@@ -445,6 +469,15 @@ e1000_probe(struct pci_dev *pdev,
e1000_check_options(adapter);
e1000_proc_dev_setup(adapter);
/* Initial Wake on LAN setting
* If APM wake is enabled in the EEPROM,
* enable the ACPI Magic Packet filter
*/
if((adapter->hw.mac_type >= e1000_82544) &&
(E1000_READ_REG(&adapter->hw, WUC) & E1000_WUC_APME))
adapter->wol |= E1000_WUFC_MAG;
/* reset the hardware with the new settings */
e1000_reset(adapter);
......@@ -555,6 +588,14 @@ e1000_sw_init(struct e1000_adapter *adapter)
case E1000_DEV_ID_82540EM:
hw->mac_type = e1000_82540;
break;
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
hw->mac_type = e1000_82545;
break;
case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER:
hw->mac_type = e1000_82546;
break;
default:
/* should never have loaded on this device */
BUG();
......@@ -590,7 +631,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
hw->adaptive_ifs = TRUE;
atomic_set(&adapter->irq_sem, 1);
spin_lock_init(&adapter->tx_lock);
spin_lock_init(&adapter->stats_lock);
}
......@@ -715,7 +755,7 @@ e1000_configure_tx(struct e1000_adapter *adapter)
uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
uint32_t tctl, tipg;
E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000FFFFFFFF));
E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL));
E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
......@@ -875,7 +915,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* set the Receive Delay Timer Register */
if(adapter->hw.mac_type == e1000_82540) {
if(adapter->hw.mac_type >= e1000_82540) {
E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_int_delay);
E1000_WRITE_REG(&adapter->hw, RDTR, 64);
......@@ -891,7 +931,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Setup the Base and Length of the Rx Descriptor Ring */
E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000FFFFFFFF));
E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
......@@ -1212,6 +1252,8 @@ e1000_watchdog(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
struct net_device *netdev = adapter->netdev;
struct e1000_desc_ring *txdr = &adapter->tx_ring;
int i;
e1000_check_for_link(&adapter->hw);
......@@ -1228,7 +1270,6 @@ e1000_watchdog(unsigned long data)
"Full Duplex" : "Half Duplex");
netif_carrier_on(netdev);
adapter->trans_finish = jiffies;
netif_wake_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
}
......@@ -1248,6 +1289,13 @@ e1000_watchdog(unsigned long data)
e1000_update_stats(adapter);
e1000_update_adaptive(&adapter->hw);
/* Early detection of hung controller */
i = txdr->next_to_clean;
if(txdr->buffer_info[i].dma &&
time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
netif_stop_queue(netdev);
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
......@@ -1310,6 +1358,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
skb->data + offset,
size,
PCI_DMA_TODEVICE);
tx_ring->buffer_info[i].time_stamp = jiffies;
len -= size;
offset += size;
......@@ -1388,20 +1437,11 @@ static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev->priv;
unsigned long flags;
int tx_flags = 0, count;
int f;
if(time_after(netdev->trans_start, adapter->trans_finish + HZ) &&
!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) {
adapter->trans_finish = jiffies;
netif_stop_queue(netdev);
return 1;
}
count = TXD_USE_COUNT(skb->len - skb->data_len,
adapter->max_data_per_txd);
for(f = 0; f < skb_shinfo(skb)->nr_frags; f++)
......@@ -1410,14 +1450,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(skb->ip_summed == CHECKSUM_HW)
count++;
spin_lock_irqsave(&adapter->tx_lock, flags);
e1000_clean_tx_irq(adapter);
if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return 1;
}
spin_unlock_irqrestore(&adapter->tx_lock, flags);
if(e1000_tx_csum(adapter, skb))
tx_flags |= E1000_TX_FLAGS_CSUM;
......@@ -1701,12 +1737,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
e1000_clean_rx_irq(adapter);
if((icr & E1000_ICR_TXDW) && spin_trylock(&adapter->tx_lock)) {
e1000_clean_tx_irq(adapter);
spin_unlock(&adapter->tx_lock);
}
i--;
}
......@@ -1753,8 +1784,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
i = (i + 1) % tx_ring->count;
tx_desc = E1000_TX_DESC(*tx_ring, i);
adapter->trans_finish = jiffies;
}
tx_ring->next_to_clean = i;
......@@ -1893,9 +1922,6 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
int reserve_len;
int i;
if(!netif_running(netdev))
return;
reserve_len = 2;
i = rx_ring->next_to_use;
......@@ -1991,32 +2017,16 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
}
}
/**
* e1000_enable_WOL - Wake On Lan Support (Magic Pkt)
* @adapter: Adapter structure
**/
void
e1000_enable_WOL(struct e1000_adapter *adapter)
e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
{
uint32_t wuc;
if(adapter->hw.mac_type < e1000_82544)
return;
if(adapter->wol) {
wuc = E1000_WUC_APME | E1000_WUC_PME_EN |
E1000_WUC_PME_STATUS | E1000_WUC_APMPME;
E1000_WRITE_REG(&adapter->hw, WUC, wuc);
struct e1000_adapter *adapter = hw->back;
E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol);
}
pci_read_config_word(adapter->pdev, reg, value);
}
void
e1000_write_pci_cfg(struct e1000_hw *hw,
uint32_t reg, uint16_t *value)
e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
{
struct e1000_adapter *adapter = hw->back;
......@@ -2101,4 +2111,93 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
}
#endif
static int
e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
struct pci_dev *pdev = NULL;
switch(event) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
pci_for_each_dev(pdev) {
if(pci_dev_driver(pdev) == &e1000_driver)
e1000_suspend(pdev, 3);
}
}
return NOTIFY_DONE;
}
static int
e1000_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
uint32_t ctrl, ctrl_ext, rctl;
netif_device_detach(netdev);
if(netif_running(netdev))
e1000_down(adapter);
if(adapter->wol) {
e1000_setup_rctl(adapter);
e1000_set_multi(netdev);
if(adapter->wol & E1000_WUFC_MC) {
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
if(adapter->hw.media_type == e1000_media_type_fiber) {
#define E1000_CTRL_ADVD3WUC 0x00100000
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
ctrl |= E1000_CTRL_ADVD3WUC;
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
}
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol);
pci_enable_wake(pdev, 3, 1);
} else {
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, 0);
pci_enable_wake(pdev, 3, 0);
}
pci_save_state(pdev, adapter->pci_state);
pci_set_power_state(pdev, 3);
return 0;
}
#ifdef CONFIG_PM
static int
e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev, adapter->pci_state);
pci_enable_wake(pdev, 0, 0);
/* Clear the wakeup status bits */
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
if(netif_running(netdev))
e1000_up(adapter);
netif_device_attach(netdev);
return 0;
}
#endif
/* e1000_main.c */
......@@ -86,12 +86,14 @@
#include <linux/interrupt.h>
#define usec_delay(x) udelay(x)
#ifndef msec_delay
#define msec_delay(x) do { if(in_interrupt()) { \
mdelay(x); \
} else { \
set_current_state(TASK_UNINTERRUPTIBLE); \
schedule_timeout((x * HZ)/1000); \
} } while(0)
#endif
#define PCI_COMMAND_REGISTER PCI_COMMAND
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
......
......@@ -524,10 +524,8 @@ static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
static int eepro100_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void eepro100_remove_one (struct pci_dev *pdev);
#ifdef CONFIG_PM
static int eepro100_suspend (struct pci_dev *pdev, u32 state);
static int eepro100_resume (struct pci_dev *pdev);
#endif
static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
static int mdio_read(long ioaddr, int phy_id, int location);
......
......@@ -845,8 +845,9 @@ pcnet32_open(struct net_device *dev)
if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))
val |= 2;
} else if (lp->options & PCNET32_PORT_ASEL) {
/* workaround for xSeries250 */
val |= 3;
/* workaround of xSeries250, turn on for 79C975 only */
i = ((lp->a.read_csr(ioaddr, 88) | (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff;
if (i == 0x2627) val |= 3;
}
lp->a.write_bcr (ioaddr, 9, val);
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -4,6 +4,9 @@
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
* Copyright 2001 Jeff Garzik <jgarzik@mandrakesoft.com>
* Portions Copyright 2001 Sun Microsystems (thockin@sun.com)
* Portions Copyright 2002 Intel (eli.kupermann@intel.com,
* christopher.leech@intel.com,
* scott.feldman@intel.com)
*/
#ifndef _LINUX_ETHTOOL_H
......@@ -268,6 +271,7 @@ struct ethtool_test {
* (ethtool_value), priv. */
#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */
#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */
#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment