Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
This commit is contained in:
commit
0ba6c33bcd
1113 changed files with 140412 additions and 55940 deletions
16
CREDITS
16
CREDITS
|
@ -1353,6 +1353,14 @@ S: Gen Stedmanstraat 212
|
|||
S: 5623 HZ Eindhoven
|
||||
S: The Netherlands
|
||||
|
||||
N: Oliver Hartkopp
|
||||
E: oliver.hartkopp@volkswagen.de
|
||||
W: http://www.volkswagen.de
|
||||
D: Controller Area Network (network layer core)
|
||||
S: Brieffach 1776
|
||||
S: 38436 Wolfsburg
|
||||
S: Germany
|
||||
|
||||
N: Andrew Haylett
|
||||
E: ajh@primag.co.uk
|
||||
D: Selection mechanism
|
||||
|
@ -3306,6 +3314,14 @@ S: Universit=E9 de Rennes I
|
|||
S: F-35042 Rennes Cedex
|
||||
S: France
|
||||
|
||||
N: Urs Thuermann
|
||||
E: urs.thuermann@volkswagen.de
|
||||
W: http://www.volkswagen.de
|
||||
D: Controller Area Network (network layer core)
|
||||
S: Brieffach 1776
|
||||
S: 38436 Wolfsburg
|
||||
S: Germany
|
||||
|
||||
N: Jon Tombs
|
||||
E: jon@gte.esi.us.es
|
||||
W: http://www.esi.us.es/~jon
|
||||
|
|
|
@ -249,15 +249,6 @@ Who: Tejun Heo <htejun@gmail.com>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: iptables SAME target
|
||||
When: 1.1. 2008
|
||||
Files: net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h
|
||||
Why: Obsolete for multiple years now, NAT core provides the same behaviour.
|
||||
Unfixable broken wrt. 32/64 bit cleanness.
|
||||
Who: Patrick McHardy <kaber@trash.net>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: The arch/ppc and include/asm-ppc directories
|
||||
When: Jun 2008
|
||||
Why: The arch/powerpc tree is the merged architecture for ppc32 and ppc64
|
||||
|
@ -289,15 +280,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: shaper network driver
|
||||
When: January 2008
|
||||
Files: drivers/net/shaper.c, include/linux/if_shaper.h
|
||||
Why: This driver has been marked obsolete for many years.
|
||||
It was only designed to work on lower speed links and has design
|
||||
flaws that lead to machine crashes. The qdisc infrastructure in
|
||||
2.4 or later kernels, provides richer features and is more robust.
|
||||
Who: Stephen Hemminger <shemminger@linux-foundation.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: i2c-i810, i2c-prosavage and i2c-savage4
|
||||
|
@ -306,3 +288,69 @@ Why: These drivers are superseded by i810fb, intelfb and savagefb.
|
|||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: bcm43xx wireless network driver
|
||||
When: 2.6.26
|
||||
Files: drivers/net/wireless/bcm43xx
|
||||
Why: This driver's functionality has been replaced by the
|
||||
mac80211-based b43 and b43legacy drivers.
|
||||
Who: John W. Linville <linville@tuxdriver.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: ieee80211 softmac wireless networking component
|
||||
When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211)
|
||||
Files: net/ieee80211/softmac
|
||||
Why: No in-kernel drivers will depend on it any longer.
|
||||
Who: John W. Linville <linville@tuxdriver.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: rc80211-simple rate control algorithm for mac80211
|
||||
When: 2.6.26
|
||||
Files: net/mac80211/rc80211-simple.c
|
||||
Why: This algorithm was provided for reference but always exhibited bad
|
||||
responsiveness and performance and has some serious flaws. It has been
|
||||
replaced by rc80211-pid.
|
||||
Who: Stefano Brivio <stefano.brivio@polimi.it>
|
||||
|
||||
---------------------------
|
||||
|
||||
What (Why):
|
||||
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
|
||||
(superseded by xt_TOS/xt_tos target & match)
|
||||
|
||||
- "forwarding" header files like ipt_mac.h in
|
||||
include/linux/netfilter_ipv4/ and include/linux/netfilter_ipv6/
|
||||
|
||||
- xt_CONNMARK match revision 0
|
||||
(superseded by xt_CONNMARK match revision 1)
|
||||
|
||||
- xt_MARK target revisions 0 and 1
|
||||
(superseded by xt_MARK match revision 2)
|
||||
|
||||
- xt_connmark match revision 0
|
||||
(superseded by xt_connmark match revision 1)
|
||||
|
||||
- xt_conntrack match revision 0
|
||||
(superseded by xt_conntrack match revision 1)
|
||||
|
||||
- xt_iprange match revision 0,
|
||||
include/linux/netfilter_ipv4/ipt_iprange.h
|
||||
(superseded by xt_iprange match revision 1)
|
||||
|
||||
- xt_mark match revision 0
|
||||
(superseded by xt_mark match revision 1)
|
||||
|
||||
When: January 2009 or Linux 2.7.0, whichever comes first
|
||||
Why: Superseded by newer revisions or modules
|
||||
Who: Jan Engelhardt <jengelh@computergmbh.de>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: b43 support for firmware revision < 410
|
||||
When: July 2008
|
||||
Why: The support code for the old firmware hurts code readability/maintainability
|
||||
and slightly hurts runtime performance. Bugfixes for the old firmware
|
||||
are not provided by Broadcom anymore.
|
||||
Who: Michael Buesch <mb@bu3sch.de>
|
||||
|
|
|
@ -24,6 +24,8 @@ baycom.txt
|
|||
- info on the driver for Baycom style amateur radio modems
|
||||
bridge.txt
|
||||
- where to get user space programs for ethernet bridging with Linux.
|
||||
can.txt
|
||||
- documentation on CAN protocol family.
|
||||
cops.txt
|
||||
- info on the COPS LocalTalk Linux driver
|
||||
cs89x0.txt
|
||||
|
@ -82,8 +84,6 @@ policy-routing.txt
|
|||
- IP policy-based routing
|
||||
ray_cs.txt
|
||||
- Raylink Wireless LAN card driver info.
|
||||
shaper.txt
|
||||
- info on the module that can shape/limit transmitted traffic.
|
||||
sk98lin.txt
|
||||
- Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
|
||||
Ethernet Adapter family driver info
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Linux Ethernet Bonding Driver HOWTO
|
||||
|
||||
Latest update: 24 April 2006
|
||||
Latest update: 12 November 2007
|
||||
|
||||
Initial release : Thomas Davis <tadavis at lbl.gov>
|
||||
Corrections, HA extensions : 2000/10/03-15 :
|
||||
|
@ -166,12 +166,17 @@ to use ifenslave.
|
|||
2. Bonding Driver Options
|
||||
=========================
|
||||
|
||||
Options for the bonding driver are supplied as parameters to
|
||||
the bonding module at load time. They may be given as command line
|
||||
arguments to the insmod or modprobe command, but are usually specified
|
||||
in either the /etc/modules.conf or /etc/modprobe.conf configuration
|
||||
file, or in a distro-specific configuration file (some of which are
|
||||
detailed in the next section).
|
||||
Options for the bonding driver are supplied as parameters to the
|
||||
bonding module at load time, or are specified via sysfs.
|
||||
|
||||
Module options may be given as command line arguments to the
|
||||
insmod or modprobe command, but are usually specified in either the
|
||||
/etc/modules.conf or /etc/modprobe.conf configuration file, or in a
|
||||
distro-specific configuration file (some of which are detailed in the next
|
||||
section).
|
||||
|
||||
Details on bonding support for sysfs is provided in the
|
||||
"Configuring Bonding Manually via Sysfs" section, below.
|
||||
|
||||
The available bonding driver parameters are listed below. If a
|
||||
parameter is not specified the default value is used. When initially
|
||||
|
@ -812,11 +817,13 @@ the system /etc/modules.conf or /etc/modprobe.conf configuration file.
|
|||
3.2 Configuration with Initscripts Support
|
||||
------------------------------------------
|
||||
|
||||
This section applies to distros using a version of initscripts
|
||||
with bonding support, for example, Red Hat Linux 9 or Red Hat
|
||||
Enterprise Linux version 3 or 4. On these systems, the network
|
||||
initialization scripts have some knowledge of bonding, and can be
|
||||
configured to control bonding devices.
|
||||
This section applies to distros using a recent version of
|
||||
initscripts with bonding support, for example, Red Hat Enterprise Linux
|
||||
version 3 or later, Fedora, etc. On these systems, the network
|
||||
initialization scripts have knowledge of bonding, and can be configured to
|
||||
control bonding devices. Note that older versions of the initscripts
|
||||
package have lower levels of support for bonding; this will be noted where
|
||||
applicable.
|
||||
|
||||
These distros will not automatically load the network adapter
|
||||
driver unless the ethX device is configured with an IP address.
|
||||
|
@ -864,11 +871,31 @@ USERCTL=no
|
|||
Be sure to change the networking specific lines (IPADDR,
|
||||
NETMASK, NETWORK and BROADCAST) to match your network configuration.
|
||||
|
||||
Finally, it is necessary to edit /etc/modules.conf (or
|
||||
/etc/modprobe.conf, depending upon your distro) to load the bonding
|
||||
module with your desired options when the bond0 interface is brought
|
||||
up. The following lines in /etc/modules.conf (or modprobe.conf) will
|
||||
load the bonding module, and select its options:
|
||||
For later versions of initscripts, such as that found with Fedora
|
||||
7 and Red Hat Enterprise Linux version 5 (or later), it is possible, and,
|
||||
indeed, preferable, to specify the bonding options in the ifcfg-bond0
|
||||
file, e.g. a line of the format:
|
||||
|
||||
BONDING_OPTS="mode=active-backup arp_interval=60 arp_ip_target=+192.168.1.254"
|
||||
|
||||
will configure the bond with the specified options. The options
|
||||
specified in BONDING_OPTS are identical to the bonding module parameters
|
||||
except for the arp_ip_target field. Each target should be included as a
|
||||
separate option and should be preceded by a '+' to indicate it should be
|
||||
added to the list of queried targets, e.g.,
|
||||
|
||||
arp_ip_target=+192.168.1.1 arp_ip_target=+192.168.1.2
|
||||
|
||||
is the proper syntax to specify multiple targets. When specifying
|
||||
options via BONDING_OPTS, it is not necessary to edit /etc/modules.conf or
|
||||
/etc/modprobe.conf.
|
||||
|
||||
For older versions of initscripts that do not support
|
||||
BONDING_OPTS, it is necessary to edit /etc/modules.conf (or
|
||||
/etc/modprobe.conf, depending upon your distro) to load the bonding module
|
||||
with your desired options when the bond0 interface is brought up. The
|
||||
following lines in /etc/modules.conf (or modprobe.conf) will load the
|
||||
bonding module, and select its options:
|
||||
|
||||
alias bond0 bonding
|
||||
options bond0 mode=balance-alb miimon=100
|
||||
|
@ -883,9 +910,10 @@ up and running.
|
|||
3.2.1 Using DHCP with Initscripts
|
||||
---------------------------------
|
||||
|
||||
Recent versions of initscripts (the version supplied with
|
||||
Fedora Core 3 and Red Hat Enterprise Linux 4 is reported to work) do
|
||||
have support for assigning IP information to bonding devices via DHCP.
|
||||
Recent versions of initscripts (the versions supplied with Fedora
|
||||
Core 3 and Red Hat Enterprise Linux 4, or later versions, are reported to
|
||||
work) have support for assigning IP information to bonding devices via
|
||||
DHCP.
|
||||
|
||||
To configure bonding for DHCP, configure it as described
|
||||
above, except replace the line "BOOTPROTO=none" with "BOOTPROTO=dhcp"
|
||||
|
@ -895,18 +923,14 @@ is case sensitive.
|
|||
3.2.2 Configuring Multiple Bonds with Initscripts
|
||||
-------------------------------------------------
|
||||
|
||||
At this writing, the initscripts package does not directly
|
||||
support loading the bonding driver multiple times, so the process for
|
||||
doing so is the same as described in the "Configuring Multiple Bonds
|
||||
Manually" section, below.
|
||||
|
||||
NOTE: It has been observed that some Red Hat supplied kernels
|
||||
are apparently unable to rename modules at load time (the "-o bond1"
|
||||
part). Attempts to pass that option to modprobe will produce an
|
||||
"Operation not permitted" error. This has been reported on some
|
||||
Fedora Core kernels, and has been seen on RHEL 4 as well. On kernels
|
||||
exhibiting this problem, it will be impossible to configure multiple
|
||||
bonds with differing parameters.
|
||||
Initscripts packages that are included with Fedora 7 and Red Hat
|
||||
Enterprise Linux 5 support multiple bonding interfaces by simply
|
||||
specifying the appropriate BONDING_OPTS= in ifcfg-bondX where X is the
|
||||
number of the bond. This support requires sysfs support in the kernel,
|
||||
and a bonding driver of version 3.0.0 or later. Other configurations may
|
||||
not support this method for specifying multiple bonding interfaces; for
|
||||
those instances, see the "Configuring Multiple Bonds Manually" section,
|
||||
below.
|
||||
|
||||
3.3 Configuring Bonding Manually with Ifenslave
|
||||
-----------------------------------------------
|
||||
|
@ -977,15 +1001,58 @@ initialization scripts lack support for configuring multiple bonds.
|
|||
options, you may wish to use the "max_bonds" module parameter,
|
||||
documented above.
|
||||
|
||||
To create multiple bonding devices with differing options, it
|
||||
is necessary to use bonding parameters exported by sysfs, documented
|
||||
in the section below.
|
||||
To create multiple bonding devices with differing options, it is
|
||||
preferrable to use bonding parameters exported by sysfs, documented in the
|
||||
section below.
|
||||
|
||||
For versions of bonding without sysfs support, the only means to
|
||||
provide multiple instances of bonding with differing options is to load
|
||||
the bonding driver multiple times. Note that current versions of the
|
||||
sysconfig network initialization scripts handle this automatically; if
|
||||
your distro uses these scripts, no special action is needed. See the
|
||||
section Configuring Bonding Devices, above, if you're not sure about your
|
||||
network initialization scripts.
|
||||
|
||||
To load multiple instances of the module, it is necessary to
|
||||
specify a different name for each instance (the module loading system
|
||||
requires that every loaded module, even multiple instances of the same
|
||||
module, have a unique name). This is accomplished by supplying multiple
|
||||
sets of bonding options in /etc/modprobe.conf, for example:
|
||||
|
||||
alias bond0 bonding
|
||||
options bond0 -o bond0 mode=balance-rr miimon=100
|
||||
|
||||
alias bond1 bonding
|
||||
options bond1 -o bond1 mode=balance-alb miimon=50
|
||||
|
||||
will load the bonding module two times. The first instance is
|
||||
named "bond0" and creates the bond0 device in balance-rr mode with an
|
||||
miimon of 100. The second instance is named "bond1" and creates the
|
||||
bond1 device in balance-alb mode with an miimon of 50.
|
||||
|
||||
In some circumstances (typically with older distributions),
|
||||
the above does not work, and the second bonding instance never sees
|
||||
its options. In that case, the second options line can be substituted
|
||||
as follows:
|
||||
|
||||
install bond1 /sbin/modprobe --ignore-install bonding -o bond1 \
|
||||
mode=balance-alb miimon=50
|
||||
|
||||
This may be repeated any number of times, specifying a new and
|
||||
unique name in place of bond1 for each subsequent instance.
|
||||
|
||||
It has been observed that some Red Hat supplied kernels are unable
|
||||
to rename modules at load time (the "-o bond1" part). Attempts to pass
|
||||
that option to modprobe will produce an "Operation not permitted" error.
|
||||
This has been reported on some Fedora Core kernels, and has been seen on
|
||||
RHEL 4 as well. On kernels exhibiting this problem, it will be impossible
|
||||
to configure multiple bonds with differing parameters (as they are older
|
||||
kernels, and also lack sysfs support).
|
||||
|
||||
3.4 Configuring Bonding Manually via Sysfs
|
||||
------------------------------------------
|
||||
|
||||
Starting with version 3.0, Channel Bonding may be configured
|
||||
Starting with version 3.0.0, Channel Bonding may be configured
|
||||
via the sysfs interface. This interface allows dynamic configuration
|
||||
of all bonds in the system without unloading the module. It also
|
||||
allows for adding and removing bonds at runtime. Ifenslave is no
|
||||
|
@ -1030,9 +1097,6 @@ To enslave interface eth0 to bond bond0:
|
|||
To free slave eth0 from bond bond0:
|
||||
# echo -eth0 > /sys/class/net/bond0/bonding/slaves
|
||||
|
||||
NOTE: The bond must be up before slaves can be added. All
|
||||
slaves are freed when the interface is brought down.
|
||||
|
||||
When an interface is enslaved to a bond, symlinks between the
|
||||
two are created in the sysfs filesystem. In this case, you would get
|
||||
/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and
|
||||
|
@ -1622,6 +1686,15 @@ one for each switch in the network). This will insure that,
|
|||
regardless of which switch is active, the ARP monitor has a suitable
|
||||
target to query.
|
||||
|
||||
Note, also, that of late many switches now support a functionality
|
||||
generally referred to as "trunk failover." This is a feature of the
|
||||
switch that causes the link state of a particular switch port to be set
|
||||
down (or up) when the state of another switch port goes down (or up).
|
||||
It's purpose is to propogate link failures from logically "exterior" ports
|
||||
to the logically "interior" ports that bonding is able to monitor via
|
||||
miimon. Availability and configuration for trunk failover varies by
|
||||
switch, but this can be a viable alternative to the ARP monitor when using
|
||||
suitable switches.
|
||||
|
||||
12. Configuring Bonding for Maximum Throughput
|
||||
==============================================
|
||||
|
@ -1709,7 +1782,7 @@ balance-rr: This mode is the only mode that will permit a single
|
|||
interfaces. It is therefore the only mode that will allow a
|
||||
single TCP/IP stream to utilize more than one interface's
|
||||
worth of throughput. This comes at a cost, however: the
|
||||
striping often results in peer systems receiving packets out
|
||||
striping generally results in peer systems receiving packets out
|
||||
of order, causing TCP/IP's congestion control system to kick
|
||||
in, often by retransmitting segments.
|
||||
|
||||
|
@ -1721,22 +1794,20 @@ balance-rr: This mode is the only mode that will permit a single
|
|||
interface's worth of throughput, even after adjusting
|
||||
tcp_reordering.
|
||||
|
||||
Note that this out of order delivery occurs when both the
|
||||
sending and receiving systems are utilizing a multiple
|
||||
interface bond. Consider a configuration in which a
|
||||
balance-rr bond feeds into a single higher capacity network
|
||||
channel (e.g., multiple 100Mb/sec ethernets feeding a single
|
||||
gigabit ethernet via an etherchannel capable switch). In this
|
||||
configuration, traffic sent from the multiple 100Mb devices to
|
||||
a destination connected to the gigabit device will not see
|
||||
packets out of order. However, traffic sent from the gigabit
|
||||
device to the multiple 100Mb devices may or may not see
|
||||
traffic out of order, depending upon the balance policy of the
|
||||
switch. Many switches do not support any modes that stripe
|
||||
traffic (instead choosing a port based upon IP or MAC level
|
||||
addresses); for those devices, traffic flowing from the
|
||||
gigabit device to the many 100Mb devices will only utilize one
|
||||
interface.
|
||||
Note that the fraction of packets that will be delivered out of
|
||||
order is highly variable, and is unlikely to be zero. The level
|
||||
of reordering depends upon a variety of factors, including the
|
||||
networking interfaces, the switch, and the topology of the
|
||||
configuration. Speaking in general terms, higher speed network
|
||||
cards produce more reordering (due to factors such as packet
|
||||
coalescing), and a "many to many" topology will reorder at a
|
||||
higher rate than a "many slow to one fast" configuration.
|
||||
|
||||
Many switches do not support any modes that stripe traffic
|
||||
(instead choosing a port based upon IP or MAC level addresses);
|
||||
for those devices, traffic for a particular connection flowing
|
||||
through the switch to a balance-rr bond will not utilize greater
|
||||
than one interface's worth of bandwidth.
|
||||
|
||||
If you are utilizing protocols other than TCP/IP, UDP for
|
||||
example, and your application can tolerate out of order
|
||||
|
@ -1936,6 +2007,10 @@ Failover may be delayed via the downdelay bonding module option.
|
|||
13.2 Duplicated Incoming Packets
|
||||
--------------------------------
|
||||
|
||||
NOTE: Starting with version 3.0.2, the bonding driver has logic to
|
||||
suppress duplicate packets, which should largely eliminate this problem.
|
||||
The following description is kept for reference.
|
||||
|
||||
It is not uncommon to observe a short burst of duplicated
|
||||
traffic when the bonding device is first used, or after it has been
|
||||
idle for some period of time. This is most easily observed by issuing
|
||||
|
@ -2096,6 +2171,9 @@ The new driver was designed to be SMP safe from the start.
|
|||
EtherExpress PRO/100 and a 3com 3c905b, for example). For most modes,
|
||||
devices need not be of the same speed.
|
||||
|
||||
Starting with version 3.2.1, bonding also supports Infiniband
|
||||
slaves in active-backup mode.
|
||||
|
||||
3. How many bonding devices can I have?
|
||||
|
||||
There is no limit.
|
||||
|
@ -2154,11 +2232,15 @@ switches currently available support 802.3ad.
|
|||
|
||||
8. Where does a bonding device get its MAC address from?
|
||||
|
||||
If not explicitly configured (with ifconfig or ip link), the
|
||||
MAC address of the bonding device is taken from its first slave
|
||||
device. This MAC address is then passed to all following slaves and
|
||||
remains persistent (even if the first slave is removed) until the
|
||||
bonding device is brought down or reconfigured.
|
||||
When using slave devices that have fixed MAC addresses, or when
|
||||
the fail_over_mac option is enabled, the bonding device's MAC address is
|
||||
the MAC address of the active slave.
|
||||
|
||||
For other configurations, if not explicitly configured (with
|
||||
ifconfig or ip link), the MAC address of the bonding device is taken from
|
||||
its first slave device. This MAC address is then passed to all following
|
||||
slaves and remains persistent (even if the first slave is removed) until
|
||||
the bonding device is brought down or reconfigured.
|
||||
|
||||
If you wish to change the MAC address, you can set it with
|
||||
ifconfig or ip link:
|
||||
|
|
629
Documentation/networking/can.txt
Normal file
629
Documentation/networking/can.txt
Normal file
|
@ -0,0 +1,629 @@
|
|||
============================================================================
|
||||
|
||||
can.txt
|
||||
|
||||
Readme file for the Controller Area Network Protocol Family (aka Socket CAN)
|
||||
|
||||
This file contains
|
||||
|
||||
1 Overview / What is Socket CAN
|
||||
|
||||
2 Motivation / Why using the socket API
|
||||
|
||||
3 Socket CAN concept
|
||||
3.1 receive lists
|
||||
3.2 local loopback of sent frames
|
||||
3.3 network security issues (capabilities)
|
||||
3.4 network problem notifications
|
||||
|
||||
4 How to use Socket CAN
|
||||
4.1 RAW protocol sockets with can_filters (SOCK_RAW)
|
||||
4.1.1 RAW socket option CAN_RAW_FILTER
|
||||
4.1.2 RAW socket option CAN_RAW_ERR_FILTER
|
||||
4.1.3 RAW socket option CAN_RAW_LOOPBACK
|
||||
4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS
|
||||
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
|
||||
4.3 connected transport protocols (SOCK_SEQPACKET)
|
||||
4.4 unconnected transport protocols (SOCK_DGRAM)
|
||||
|
||||
5 Socket CAN core module
|
||||
5.1 can.ko module params
|
||||
5.2 procfs content
|
||||
5.3 writing own CAN protocol modules
|
||||
|
||||
6 CAN network drivers
|
||||
6.1 general settings
|
||||
6.2 local loopback of sent frames
|
||||
6.3 CAN controller hardware filters
|
||||
6.4 currently supported CAN hardware
|
||||
6.5 todo
|
||||
|
||||
7 Credits
|
||||
|
||||
============================================================================
|
||||
|
||||
1. Overview / What is Socket CAN
|
||||
--------------------------------
|
||||
|
||||
The socketcan package is an implementation of CAN protocols
|
||||
(Controller Area Network) for Linux. CAN is a networking technology
|
||||
which has widespread use in automation, embedded devices, and
|
||||
automotive fields. While there have been other CAN implementations
|
||||
for Linux based on character devices, Socket CAN uses the Berkeley
|
||||
socket API, the Linux network stack and implements the CAN device
|
||||
drivers as network interfaces. The CAN socket API has been designed
|
||||
as similar as possible to the TCP/IP protocols to allow programmers,
|
||||
familiar with network programming, to easily learn how to use CAN
|
||||
sockets.
|
||||
|
||||
2. Motivation / Why using the socket API
|
||||
----------------------------------------
|
||||
|
||||
There have been CAN implementations for Linux before Socket CAN so the
|
||||
question arises, why we have started another project. Most existing
|
||||
implementations come as a device driver for some CAN hardware, they
|
||||
are based on character devices and provide comparatively little
|
||||
functionality. Usually, there is only a hardware-specific device
|
||||
driver which provides a character device interface to send and
|
||||
receive raw CAN frames, directly to/from the controller hardware.
|
||||
Queueing of frames and higher-level transport protocols like ISO-TP
|
||||
have to be implemented in user space applications. Also, most
|
||||
character-device implementations support only one single process to
|
||||
open the device at a time, similar to a serial interface. Exchanging
|
||||
the CAN controller requires employment of another device driver and
|
||||
often the need for adaption of large parts of the application to the
|
||||
new driver's API.
|
||||
|
||||
Socket CAN was designed to overcome all of these limitations. A new
|
||||
protocol family has been implemented which provides a socket interface
|
||||
to user space applications and which builds upon the Linux network
|
||||
layer, so to use all of the provided queueing functionality. A device
|
||||
driver for CAN controller hardware registers itself with the Linux
|
||||
network layer as a network device, so that CAN frames from the
|
||||
controller can be passed up to the network layer and on to the CAN
|
||||
protocol family module and also vice-versa. Also, the protocol family
|
||||
module provides an API for transport protocol modules to register, so
|
||||
that any number of transport protocols can be loaded or unloaded
|
||||
dynamically. In fact, the can core module alone does not provide any
|
||||
protocol and cannot be used without loading at least one additional
|
||||
protocol module. Multiple sockets can be opened at the same time,
|
||||
on different or the same protocol module and they can listen/send
|
||||
frames on different or the same CAN IDs. Several sockets listening on
|
||||
the same interface for frames with the same CAN ID are all passed the
|
||||
same received matching CAN frames. An application wishing to
|
||||
communicate using a specific transport protocol, e.g. ISO-TP, just
|
||||
selects that protocol when opening the socket, and then can read and
|
||||
write application data byte streams, without having to deal with
|
||||
CAN-IDs, frames, etc.
|
||||
|
||||
Similar functionality visible from user-space could be provided by a
|
||||
character device, too, but this would lead to a technically inelegant
|
||||
solution for a couple of reasons:
|
||||
|
||||
* Intricate usage. Instead of passing a protocol argument to
|
||||
socket(2) and using bind(2) to select a CAN interface and CAN ID, an
|
||||
application would have to do all these operations using ioctl(2)s.
|
||||
|
||||
* Code duplication. A character device cannot make use of the Linux
|
||||
network queueing code, so all that code would have to be duplicated
|
||||
for CAN networking.
|
||||
|
||||
* Abstraction. In most existing character-device implementations, the
|
||||
hardware-specific device driver for a CAN controller directly
|
||||
provides the character device for the application to work with.
|
||||
This is at least very unusual in Unix systems for both, char and
|
||||
block devices. For example you don't have a character device for a
|
||||
certain UART of a serial interface, a certain sound chip in your
|
||||
computer, a SCSI or IDE controller providing access to your hard
|
||||
disk or tape streamer device. Instead, you have abstraction layers
|
||||
which provide a unified character or block device interface to the
|
||||
application on the one hand, and a interface for hardware-specific
|
||||
device drivers on the other hand. These abstractions are provided
|
||||
by subsystems like the tty layer, the audio subsystem or the SCSI
|
||||
and IDE subsystems for the devices mentioned above.
|
||||
|
||||
The easiest way to implement a CAN device driver is as a character
|
||||
device without such a (complete) abstraction layer, as is done by most
|
||||
existing drivers. The right way, however, would be to add such a
|
||||
layer with all the functionality like registering for certain CAN
|
||||
IDs, supporting several open file descriptors and (de)multiplexing
|
||||
CAN frames between them, (sophisticated) queueing of CAN frames, and
|
||||
providing an API for device drivers to register with. However, then
|
||||
it would be no more difficult, or may be even easier, to use the
|
||||
networking framework provided by the Linux kernel, and this is what
|
||||
Socket CAN does.
|
||||
|
||||
The use of the networking framework of the Linux kernel is just the
|
||||
natural and most appropriate way to implement CAN for Linux.
|
||||
|
||||
3. Socket CAN concept
|
||||
---------------------
|
||||
|
||||
As described in chapter 2 it is the main goal of Socket CAN to
|
||||
provide a socket interface to user space applications which builds
|
||||
upon the Linux network layer. In contrast to the commonly known
|
||||
TCP/IP and ethernet networking, the CAN bus is a broadcast-only(!)
|
||||
medium that has no MAC-layer addressing like ethernet. The CAN-identifier
|
||||
(can_id) is used for arbitration on the CAN-bus. Therefore the CAN-IDs
|
||||
have to be chosen uniquely on the bus. When designing a CAN-ECU
|
||||
network the CAN-IDs are mapped to be sent by a specific ECU.
|
||||
For this reason a CAN-ID can be treated best as a kind of source address.
|
||||
|
||||
3.1 receive lists
|
||||
|
||||
The network transparent access of multiple applications leads to the
|
||||
problem that different applications may be interested in the same
|
||||
CAN-IDs from the same CAN network interface. The Socket CAN core
|
||||
module - which implements the protocol family CAN - provides several
|
||||
high efficient receive lists for this reason. If e.g. a user space
|
||||
application opens a CAN RAW socket, the raw protocol module itself
|
||||
requests the (range of) CAN-IDs from the Socket CAN core that are
|
||||
requested by the user. The subscription and unsubscription of
|
||||
CAN-IDs can be done for specific CAN interfaces or for all(!) known
|
||||
CAN interfaces with the can_rx_(un)register() functions provided to
|
||||
CAN protocol modules by the SocketCAN core (see chapter 5).
|
||||
To optimize the CPU usage at runtime the receive lists are split up
|
||||
into several specific lists per device that match the requested
|
||||
filter complexity for a given use-case.
|
||||
|
||||
3.2 local loopback of sent frames
|
||||
|
||||
As known from other networking concepts the data exchanging
|
||||
applications may run on the same or different nodes without any
|
||||
change (except for the according addressing information):
|
||||
|
||||
___ ___ ___ _______ ___
|
||||
| _ | | _ | | _ | | _ _ | | _ |
|
||||
||A|| ||B|| ||C|| ||A| |B|| ||C||
|
||||
|___| |___| |___| |_______| |___|
|
||||
| | | | |
|
||||
-----------------(1)- CAN bus -(2)---------------
|
||||
|
||||
To ensure that application A receives the same information in the
|
||||
example (2) as it would receive in example (1) there is need for
|
||||
some kind of local loopback of the sent CAN frames on the appropriate
|
||||
node.
|
||||
|
||||
The Linux network devices (by default) just can handle the
|
||||
transmission and reception of media dependent frames. Due to the
|
||||
arbritration on the CAN bus the transmission of a low prio CAN-ID
|
||||
may be delayed by the reception of a high prio CAN frame. To
|
||||
reflect the correct* traffic on the node the loopback of the sent
|
||||
data has to be performed right after a successful transmission. If
|
||||
the CAN network interface is not capable of performing the loopback for
|
||||
some reason the SocketCAN core can do this task as a fallback solution.
|
||||
See chapter 6.2 for details (recommended).
|
||||
|
||||
The loopback functionality is enabled by default to reflect standard
|
||||
networking behaviour for CAN applications. Due to some requests from
|
||||
the RT-SocketCAN group the loopback optionally may be disabled for each
|
||||
separate socket. See sockopts from the CAN RAW sockets in chapter 4.1.
|
||||
|
||||
* = you really like to have this when you're running analyser tools
|
||||
like 'candump' or 'cansniffer' on the (same) node.
|
||||
|
||||
3.3 network security issues (capabilities)
|
||||
|
||||
The Controller Area Network is a local field bus transmitting only
|
||||
broadcast messages without any routing and security concepts.
|
||||
In the majority of cases the user application has to deal with
|
||||
raw CAN frames. Therefore it might be reasonable NOT to restrict
|
||||
the CAN access only to the user root, as known from other networks.
|
||||
Since the currently implemented CAN_RAW and CAN_BCM sockets can only
|
||||
send and receive frames to/from CAN interfaces it does not affect
|
||||
security of others networks to allow all users to access the CAN.
|
||||
To enable non-root users to access CAN_RAW and CAN_BCM protocol
|
||||
sockets the Kconfig options CAN_RAW_USER and/or CAN_BCM_USER may be
|
||||
selected at kernel compile time.
|
||||
|
||||
3.4 network problem notifications
|
||||
|
||||
The use of the CAN bus may lead to several problems on the physical
|
||||
and media access control layer. Detecting and logging of these lower
|
||||
layer problems is a vital requirement for CAN users to identify
|
||||
hardware issues on the physical transceiver layer as well as
|
||||
arbitration problems and error frames caused by the different
|
||||
ECUs. The occurrence of detected errors are important for diagnosis
|
||||
and have to be logged together with the exact timestamp. For this
|
||||
reason the CAN interface driver can generate so called Error Frames
|
||||
that can optionally be passed to the user application in the same
|
||||
way as other CAN frames. Whenever an error on the physical layer
|
||||
or the MAC layer is detected (e.g. by the CAN controller) the driver
|
||||
creates an appropriate error frame. Error frames can be requested by
|
||||
the user application using the common CAN filter mechanisms. Inside
|
||||
this filter definition the (interested) type of errors may be
|
||||
selected. The reception of error frames is disabled by default.
|
||||
|
||||
4. How to use Socket CAN
|
||||
------------------------
|
||||
|
||||
Like TCP/IP, you first need to open a socket for communicating over a
|
||||
CAN network. Since Socket CAN implements a new protocol family, you
|
||||
need to pass PF_CAN as the first argument to the socket(2) system
|
||||
call. Currently, there are two CAN protocols to choose from, the raw
|
||||
socket protocol and the broadcast manager (BCM). So to open a socket,
|
||||
you would write
|
||||
|
||||
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
|
||||
and
|
||||
|
||||
s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
|
||||
|
||||
respectively. After the successful creation of the socket, you would
|
||||
normally use the bind(2) system call to bind the socket to a CAN
|
||||
interface (which is different from TCP/IP due to different addressing
|
||||
- see chapter 3). After binding (CAN_RAW) or connecting (CAN_BCM)
|
||||
the socket, you can read(2) and write(2) from/to the socket or use
|
||||
send(2), sendto(2), sendmsg(2) and the recv* counterpart operations
|
||||
on the socket as usual. There are also CAN specific socket options
|
||||
described below.
|
||||
|
||||
The basic CAN frame structure and the sockaddr structure are defined
|
||||
in include/linux/can.h:
|
||||
|
||||
struct can_frame {
|
||||
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
|
||||
__u8 can_dlc; /* data length code: 0 .. 8 */
|
||||
__u8 data[8] __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
The alignment of the (linear) payload data[] to a 64bit boundary
|
||||
allows the user to define own structs and unions to easily access the
|
||||
CAN payload. There is no given byteorder on the CAN bus by
|
||||
default. A read(2) system call on a CAN_RAW socket transfers a
|
||||
struct can_frame to the user space.
|
||||
|
||||
The sockaddr_can structure has an interface index like the
|
||||
PF_PACKET socket, that also binds to a specific interface:
|
||||
|
||||
struct sockaddr_can {
|
||||
sa_family_t can_family;
|
||||
int can_ifindex;
|
||||
union {
|
||||
struct { canid_t rx_id, tx_id; } tp16;
|
||||
struct { canid_t rx_id, tx_id; } tp20;
|
||||
struct { canid_t rx_id, tx_id; } mcnet;
|
||||
struct { canid_t rx_id, tx_id; } isotp;
|
||||
} can_addr;
|
||||
};
|
||||
|
||||
To determine the interface index an appropriate ioctl() has to
|
||||
be used (example for CAN_RAW sockets without error checking):
|
||||
|
||||
int s;
|
||||
struct sockaddr_can addr;
|
||||
struct ifreq ifr;
|
||||
|
||||
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
|
||||
strcpy(ifr.ifr_name, "can0" );
|
||||
ioctl(s, SIOCGIFINDEX, &ifr);
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
bind(s, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
(..)
|
||||
|
||||
To bind a socket to all(!) CAN interfaces the interface index must
|
||||
be 0 (zero). In this case the socket receives CAN frames from every
|
||||
enabled CAN interface. To determine the originating CAN interface
|
||||
the system call recvfrom(2) may be used instead of read(2). To send
|
||||
on a socket that is bound to 'any' interface sendto(2) is needed to
|
||||
specify the outgoing interface.
|
||||
|
||||
Reading CAN frames from a bound CAN_RAW socket (see above) consists
|
||||
of reading a struct can_frame:
|
||||
|
||||
struct can_frame frame;
|
||||
|
||||
nbytes = read(s, &frame, sizeof(struct can_frame));
|
||||
|
||||
if (nbytes < 0) {
|
||||
perror("can raw socket read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* paraniod check ... */
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* do something with the received CAN frame */
|
||||
|
||||
Writing CAN frames can be done similarly, with the write(2) system call:
|
||||
|
||||
nbytes = write(s, &frame, sizeof(struct can_frame));
|
||||
|
||||
When the CAN interface is bound to 'any' existing CAN interface
|
||||
(addr.can_ifindex = 0) it is recommended to use recvfrom(2) if the
|
||||
information about the originating CAN interface is needed:
|
||||
|
||||
struct sockaddr_can addr;
|
||||
struct ifreq ifr;
|
||||
socklen_t len = sizeof(addr);
|
||||
struct can_frame frame;
|
||||
|
||||
nbytes = recvfrom(s, &frame, sizeof(struct can_frame),
|
||||
0, (struct sockaddr*)&addr, &len);
|
||||
|
||||
/* get interface name of the received CAN frame */
|
||||
ifr.ifr_ifindex = addr.can_ifindex;
|
||||
ioctl(s, SIOCGIFNAME, &ifr);
|
||||
printf("Received a CAN frame from interface %s", ifr.ifr_name);
|
||||
|
||||
To write CAN frames on sockets bound to 'any' CAN interface the
|
||||
outgoing interface has to be defined certainly.
|
||||
|
||||
strcpy(ifr.ifr_name, "can0");
|
||||
ioctl(s, SIOCGIFINDEX, &ifr);
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
nbytes = sendto(s, &frame, sizeof(struct can_frame),
|
||||
0, (struct sockaddr*)&addr, sizeof(addr));
|
||||
|
||||
4.1 RAW protocol sockets with can_filters (SOCK_RAW)
|
||||
|
||||
Using CAN_RAW sockets is extensively comparable to the commonly
|
||||
known access to CAN character devices. To meet the new possibilities
|
||||
provided by the multi user SocketCAN approach, some reasonable
|
||||
defaults are set at RAW socket binding time:
|
||||
|
||||
- The filters are set to exactly one filter receiving everything
|
||||
- The socket only receives valid data frames (=> no error frames)
|
||||
- The loopback of sent CAN frames is enabled (see chapter 3.2)
|
||||
- The socket does not receive its own sent frames (in loopback mode)
|
||||
|
||||
These default settings may be changed before or after binding the socket.
|
||||
To use the referenced definitions of the socket options for CAN_RAW
|
||||
sockets, include <linux/can/raw.h>.
|
||||
|
||||
4.1.1 RAW socket option CAN_RAW_FILTER
|
||||
|
||||
The reception of CAN frames using CAN_RAW sockets can be controlled
|
||||
by defining 0 .. n filters with the CAN_RAW_FILTER socket option.
|
||||
|
||||
The CAN filter structure is defined in include/linux/can.h:
|
||||
|
||||
struct can_filter {
|
||||
canid_t can_id;
|
||||
canid_t can_mask;
|
||||
};
|
||||
|
||||
A filter matches, when
|
||||
|
||||
<received_can_id> & mask == can_id & mask
|
||||
|
||||
which is analogous to known CAN controllers hardware filter semantics.
|
||||
The filter can be inverted in this semantic, when the CAN_INV_FILTER
|
||||
bit is set in can_id element of the can_filter structure. In
|
||||
contrast to CAN controller hardware filters the user may set 0 .. n
|
||||
receive filters for each open socket separately:
|
||||
|
||||
struct can_filter rfilter[2];
|
||||
|
||||
rfilter[0].can_id = 0x123;
|
||||
rfilter[0].can_mask = CAN_SFF_MASK;
|
||||
rfilter[1].can_id = 0x200;
|
||||
rfilter[1].can_mask = 0x700;
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
|
||||
|
||||
To disable the reception of CAN frames on the selected CAN_RAW socket:
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
|
||||
To set the filters to zero filters is quite obsolete as not read
|
||||
data causes the raw socket to discard the received CAN frames. But
|
||||
having this 'send only' use-case we may remove the receive list in the
|
||||
Kernel to save a little (really a very little!) CPU usage.
|
||||
|
||||
4.1.2 RAW socket option CAN_RAW_ERR_FILTER
|
||||
|
||||
As described in chapter 3.4 the CAN interface driver can generate so
|
||||
called Error Frames that can optionally be passed to the user
|
||||
application in the same way as other CAN frames. The possible
|
||||
errors are divided into different error classes that may be filtered
|
||||
using the appropriate error mask. To register for every possible
|
||||
error condition CAN_ERR_MASK can be used as value for the error mask.
|
||||
The values for the error mask are defined in linux/can/error.h .
|
||||
|
||||
can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||
&err_mask, sizeof(err_mask));
|
||||
|
||||
4.1.3 RAW socket option CAN_RAW_LOOPBACK
|
||||
|
||||
To meet multi user needs the local loopback is enabled by default
|
||||
(see chapter 3.2 for details). But in some embedded use-cases
|
||||
(e.g. when only one application uses the CAN bus) this loopback
|
||||
functionality can be disabled (separately for each socket):
|
||||
|
||||
int loopback = 0; /* 0 = disabled, 1 = enabled (default) */
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));
|
||||
|
||||
4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS
|
||||
|
||||
When the local loopback is enabled, all the sent CAN frames are
|
||||
looped back to the open CAN sockets that registered for the CAN
|
||||
frames' CAN-ID on this given interface to meet the multi user
|
||||
needs. The reception of the CAN frames on the same socket that was
|
||||
sending the CAN frame is assumed to be unwanted and therefore
|
||||
disabled by default. This default behaviour may be changed on
|
||||
demand:
|
||||
|
||||
int recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
|
||||
&recv_own_msgs, sizeof(recv_own_msgs));
|
||||
|
||||
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
|
||||
4.3 connected transport protocols (SOCK_SEQPACKET)
|
||||
4.4 unconnected transport protocols (SOCK_DGRAM)
|
||||
|
||||
|
||||
5. Socket CAN core module
|
||||
-------------------------
|
||||
|
||||
The Socket CAN core module implements the protocol family
|
||||
PF_CAN. CAN protocol modules are loaded by the core module at
|
||||
runtime. The core module provides an interface for CAN protocol
|
||||
modules to subscribe needed CAN IDs (see chapter 3.1).
|
||||
|
||||
5.1 can.ko module params
|
||||
|
||||
- stats_timer: To calculate the Socket CAN core statistics
|
||||
(e.g. current/maximum frames per second) this 1 second timer is
|
||||
invoked at can.ko module start time by default. This timer can be
|
||||
disabled by using stattimer=0 on the module comandline.
|
||||
|
||||
- debug: (removed since SocketCAN SVN r546)
|
||||
|
||||
5.2 procfs content
|
||||
|
||||
As described in chapter 3.1 the Socket CAN core uses several filter
|
||||
lists to deliver received CAN frames to CAN protocol modules. These
|
||||
receive lists, their filters and the count of filter matches can be
|
||||
checked in the appropriate receive list. All entries contain the
|
||||
device and a protocol module identifier:
|
||||
|
||||
foo@bar:~$ cat /proc/net/can/rcvlist_all
|
||||
|
||||
receive list 'rx_all':
|
||||
(vcan3: no entry)
|
||||
(vcan2: no entry)
|
||||
(vcan1: no entry)
|
||||
device can_id can_mask function userdata matches ident
|
||||
vcan0 000 00000000 f88e6370 f6c6f400 0 raw
|
||||
(any: no entry)
|
||||
|
||||
In this example an application requests any CAN traffic from vcan0.
|
||||
|
||||
rcvlist_all - list for unfiltered entries (no filter operations)
|
||||
rcvlist_eff - list for single extended frame (EFF) entries
|
||||
rcvlist_err - list for error frames masks
|
||||
rcvlist_fil - list for mask/value filters
|
||||
rcvlist_inv - list for mask/value filters (inverse semantic)
|
||||
rcvlist_sff - list for single standard frame (SFF) entries
|
||||
|
||||
Additional procfs files in /proc/net/can
|
||||
|
||||
stats - Socket CAN core statistics (rx/tx frames, match ratios, ...)
|
||||
reset_stats - manual statistic reset
|
||||
version - prints the Socket CAN core version and the ABI version
|
||||
|
||||
5.3 writing own CAN protocol modules
|
||||
|
||||
To implement a new protocol in the protocol family PF_CAN a new
|
||||
protocol has to be defined in include/linux/can.h .
|
||||
The prototypes and definitions to use the Socket CAN core can be
|
||||
accessed by including include/linux/can/core.h .
|
||||
In addition to functions that register the CAN protocol and the
|
||||
CAN device notifier chain there are functions to subscribe CAN
|
||||
frames received by CAN interfaces and to send CAN frames:
|
||||
|
||||
can_rx_register - subscribe CAN frames from a specific interface
|
||||
can_rx_unregister - unsubscribe CAN frames from a specific interface
|
||||
can_send - transmit a CAN frame (optional with local loopback)
|
||||
|
||||
For details see the kerneldoc documentation in net/can/af_can.c or
|
||||
the source code of net/can/raw.c or net/can/bcm.c .
|
||||
|
||||
6. CAN network drivers
|
||||
----------------------
|
||||
|
||||
Writing a CAN network device driver is much easier than writing a
|
||||
CAN character device driver. Similar to other known network device
|
||||
drivers you mainly have to deal with:
|
||||
|
||||
- TX: Put the CAN frame from the socket buffer to the CAN controller.
|
||||
- RX: Put the CAN frame from the CAN controller to the socket buffer.
|
||||
|
||||
See e.g. at Documentation/networking/netdevices.txt . The differences
|
||||
for writing CAN network device driver are described below:
|
||||
|
||||
6.1 general settings
|
||||
|
||||
dev->type = ARPHRD_CAN; /* the netdevice hardware type */
|
||||
dev->flags = IFF_NOARP; /* CAN has no arp */
|
||||
|
||||
dev->mtu = sizeof(struct can_frame);
|
||||
|
||||
The struct can_frame is the payload of each socket buffer in the
|
||||
protocol family PF_CAN.
|
||||
|
||||
6.2 local loopback of sent frames
|
||||
|
||||
As described in chapter 3.2 the CAN network device driver should
|
||||
support a local loopback functionality similar to the local echo
|
||||
e.g. of tty devices. In this case the driver flag IFF_ECHO has to be
|
||||
set to prevent the PF_CAN core from locally echoing sent frames
|
||||
(aka loopback) as fallback solution:
|
||||
|
||||
dev->flags = (IFF_NOARP | IFF_ECHO);
|
||||
|
||||
6.3 CAN controller hardware filters
|
||||
|
||||
To reduce the interrupt load on deep embedded systems some CAN
|
||||
controllers support the filtering of CAN IDs or ranges of CAN IDs.
|
||||
These hardware filter capabilities vary from controller to
|
||||
controller and have to be identified as not feasible in a multi-user
|
||||
networking approach. The use of the very controller specific
|
||||
hardware filters could make sense in a very dedicated use-case, as a
|
||||
filter on driver level would affect all users in the multi-user
|
||||
system. The high efficient filter sets inside the PF_CAN core allow
|
||||
to set different multiple filters for each socket separately.
|
||||
Therefore the use of hardware filters goes to the category 'handmade
|
||||
tuning on deep embedded systems'. The author is running a MPC603e
|
||||
@133MHz with four SJA1000 CAN controllers from 2002 under heavy bus
|
||||
load without any problems ...
|
||||
|
||||
6.4 currently supported CAN hardware (September 2007)
|
||||
|
||||
On the project website http://developer.berlios.de/projects/socketcan
|
||||
there are different drivers available:
|
||||
|
||||
vcan: Virtual CAN interface driver (if no real hardware is available)
|
||||
sja1000: Philips SJA1000 CAN controller (recommended)
|
||||
i82527: Intel i82527 CAN controller
|
||||
mscan: Motorola/Freescale CAN controller (e.g. inside SOC MPC5200)
|
||||
ccan: CCAN controller core (e.g. inside SOC h7202)
|
||||
slcan: For a bunch of CAN adaptors that are attached via a
|
||||
serial line ASCII protocol (for serial / USB adaptors)
|
||||
|
||||
Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport)
|
||||
from PEAK Systemtechnik support the CAN netdevice driver model
|
||||
since Linux driver v6.0: http://www.peak-system.com/linux/index.htm
|
||||
|
||||
Please check the Mailing Lists on the berlios OSS project website.
|
||||
|
||||
6.5 todo (September 2007)
|
||||
|
||||
The configuration interface for CAN network drivers is still an open
|
||||
issue that has not been finalized in the socketcan project. Also the
|
||||
idea of having a library module (candev.ko) that holds functions
|
||||
that are needed by all CAN netdevices is not ready to ship.
|
||||
Your contribution is welcome.
|
||||
|
||||
7. Credits
|
||||
----------
|
||||
|
||||
Oliver Hartkopp (PF_CAN core, filters, drivers, bcm)
|
||||
Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan)
|
||||
Jan Kizka (RT-SocketCAN core, Socket-API reconciliation)
|
||||
Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews)
|
||||
Robert Schwebel (design reviews, PTXdist integration)
|
||||
Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers)
|
||||
Benedikt Spranger (reviews)
|
||||
Thomas Gleixner (LKML reviews, coding style, posting hints)
|
||||
Andrey Volkov (kernel subtree structure, ioctls, mscan driver)
|
||||
Matthias Brukner (first SJA1000 CAN netdevice implementation Q2/2003)
|
||||
Klaus Hitschler (PEAK driver integration)
|
||||
Uwe Koppe (CAN netdevices with PF_PACKET approach)
|
||||
Michael Schulze (driver layer loopback requirement, RT CAN drivers review)
|
|
@ -14,24 +14,35 @@ Introduction
|
|||
============
|
||||
|
||||
Datagram Congestion Control Protocol (DCCP) is an unreliable, connection
|
||||
based protocol designed to solve issues present in UDP and TCP particularly
|
||||
for real time and multimedia traffic.
|
||||
oriented protocol designed to solve issues present in UDP and TCP, particularly
|
||||
for real-time and multimedia (streaming) traffic.
|
||||
It divides into a base protocol (RFC 4340) and plugable congestion control
|
||||
modules called CCIDs. Like plugable TCP congestion control, at least one CCID
|
||||
needs to be enabled in order for the protocol to function properly. In the Linux
|
||||
implementation, this is the TCP-like CCID2 (RFC 4341). Additional CCIDs, such as
|
||||
the TCP-friendly CCID3 (RFC 4342), are optional.
|
||||
For a brief introduction to CCIDs and suggestions for choosing a CCID to match
|
||||
given applications, see section 10 of RFC 4340.
|
||||
|
||||
It has a base protocol and pluggable congestion control IDs (CCIDs).
|
||||
|
||||
It is at proposed standard RFC status and the homepage for DCCP as a protocol
|
||||
is at:
|
||||
http://www.read.cs.ucla.edu/dccp/
|
||||
DCCP is a Proposed Standard (RFC 2026), and the homepage for DCCP as a protocol
|
||||
is at http://www.ietf.org/html.charters/dccp-charter.html
|
||||
|
||||
Missing features
|
||||
================
|
||||
|
||||
The DCCP implementation does not currently have all the features that are in
|
||||
the RFC.
|
||||
The Linux DCCP implementation does not currently support all the features that are
|
||||
specified in RFCs 4340...42.
|
||||
|
||||
The known bugs are at:
|
||||
http://linux-net.osdl.org/index.php/TODO#DCCP
|
||||
|
||||
For more up-to-date versions of the DCCP implementation, please consider using
|
||||
the experimental DCCP test tree; instructions for checking this out are on:
|
||||
http://linux-net.osdl.org/index.php/DCCP_Testing#Experimental_DCCP_source_tree
|
||||
|
||||
|
||||
Socket options
|
||||
==============
|
||||
|
||||
|
@ -46,6 +57,12 @@ can be set before calling bind().
|
|||
DCCP_SOCKOPT_GET_CUR_MPS is read-only and retrieves the current maximum packet
|
||||
size (application payload size) in bytes, see RFC 4340, section 14.
|
||||
|
||||
DCCP_SOCKOPT_SERVER_TIMEWAIT enables the server (listening socket) to hold
|
||||
timewait state when closing the connection (RFC 4340, 8.3). The usual case is
|
||||
that the closing server sends a CloseReq, whereupon the client holds timewait
|
||||
state. When this boolean socket option is on, the server sends a Close instead
|
||||
and will enter TIMEWAIT. This option must be set after accept() returns.
|
||||
|
||||
DCCP_SOCKOPT_SEND_CSCOV and DCCP_SOCKOPT_RECV_CSCOV are used for setting the
|
||||
partial checksum coverage (RFC 4340, sec. 9.2). The default is that checksums
|
||||
always cover the entire packet and that only fully covered application data is
|
||||
|
@ -72,6 +89,8 @@ DCCP_SOCKOPT_CCID_TX_INFO
|
|||
Returns a `struct tfrc_tx_info' in optval; the buffer for optval and
|
||||
optlen must be set to at least sizeof(struct tfrc_tx_info).
|
||||
|
||||
On unidirectional connections it is useful to close the unused half-connection
|
||||
via shutdown (SHUT_WR or SHUT_RD): this will reduce per-packet processing costs.
|
||||
|
||||
Sysctl variables
|
||||
================
|
||||
|
@ -123,6 +142,12 @@ sync_ratelimit = 125 ms
|
|||
sequence-invalid packets on the same socket (RFC 4340, 7.5.4). The unit
|
||||
of this parameter is milliseconds; a value of 0 disables rate-limiting.
|
||||
|
||||
IOCTLS
|
||||
======
|
||||
FIONREAD
|
||||
Works as in udp(7): returns in the `int' argument pointer the size of
|
||||
the next pending datagram in bytes, or 0 when no datagram is pending.
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
|
|
|
@ -446,6 +446,33 @@ tcp_dma_copybreak - INTEGER
|
|||
and CONFIG_NET_DMA is enabled.
|
||||
Default: 4096
|
||||
|
||||
UDP variables:
|
||||
|
||||
udp_mem - vector of 3 INTEGERs: min, pressure, max
|
||||
Number of pages allowed for queueing by all UDP sockets.
|
||||
|
||||
min: Below this number of pages UDP is not bothered about its
|
||||
memory appetite. When amount of memory allocated by UDP exceeds
|
||||
this number, UDP starts to moderate memory usage.
|
||||
|
||||
pressure: This value was introduced to follow format of tcp_mem.
|
||||
|
||||
max: Number of pages allowed for queueing by all UDP sockets.
|
||||
|
||||
Default is calculated at boot time from amount of available memory.
|
||||
|
||||
udp_rmem_min - INTEGER
|
||||
Minimal size of receive buffer used by UDP sockets in moderation.
|
||||
Each UDP socket is able to use the size for receiving data, even if
|
||||
total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
|
||||
Default: 4096
|
||||
|
||||
udp_wmem_min - INTEGER
|
||||
Minimal size of send buffer used by UDP sockets in moderation.
|
||||
Each UDP socket is able to use the size for sending data, even if
|
||||
total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
|
||||
Default: 4096
|
||||
|
||||
CIPSOv4 Variables:
|
||||
|
||||
cipso_cache_enable - BOOLEAN
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
Traffic Shaper For Linux
|
||||
|
||||
This is the current BETA release of the traffic shaper for Linux. It works
|
||||
within the following limits:
|
||||
|
||||
o Minimum shaping speed is currently about 9600 baud (it can only
|
||||
shape down to 1 byte per clock tick)
|
||||
|
||||
o Maximum is about 256K, it will go above this but get a bit blocky.
|
||||
|
||||
o If you ifconfig the master device that a shaper is attached to down
|
||||
then your machine will follow.
|
||||
|
||||
o The shaper must be a module.
|
||||
|
||||
|
||||
Setup:
|
||||
|
||||
A shaper device is configured using the shapeconfig program.
|
||||
Typically you will do something like this
|
||||
|
||||
shapecfg attach shaper0 eth1
|
||||
shapecfg speed shaper0 64000
|
||||
ifconfig shaper0 myhost netmask 255.255.255.240 broadcast 1.2.3.4.255 up
|
||||
route add -net some.network netmask a.b.c.d dev shaper0
|
||||
|
||||
The shaper should have the same IP address as the device it is attached to
|
||||
for normal use.
|
||||
|
||||
Gotchas:
|
||||
|
||||
The shaper shapes transmitted traffic. It's rather impossible to
|
||||
shape received traffic except at the end (or a router) transmitting it.
|
||||
|
||||
Gated/routed/rwhod/mrouted all see the shaper as an additional device
|
||||
and will treat it as such unless patched. Note that for mrouted you can run
|
||||
mrouted tunnels via a traffic shaper to control bandwidth usage.
|
||||
|
||||
The shaper is device/route based. This makes it very easy to use
|
||||
with any setup BUT less flexible. You may need to use iproute2 to set up
|
||||
multiple route tables to get the flexibility.
|
||||
|
||||
There is no "borrowing" or "sharing" scheme. This is a simple
|
||||
traffic limiter. We implement Van Jacobson and Sally Floyd's CBQ
|
||||
architecture into Linux 2.2. This is the preferred solution. Shaper is
|
||||
for simple or back compatible setups.
|
||||
|
||||
Alan
|
|
@ -236,7 +236,7 @@
|
|||
|
||||
This displays UDP-Lite statistics variables, whose meaning is as follows.
|
||||
|
||||
InDatagrams: Total number of received datagrams.
|
||||
InDatagrams: The total number of datagrams delivered to users.
|
||||
|
||||
NoPorts: Number of packets received to an unknown port.
|
||||
These cases are counted separately (not as InErrors).
|
||||
|
|
70
Documentation/networking/xfrm_proc.txt
Normal file
70
Documentation/networking/xfrm_proc.txt
Normal file
|
@ -0,0 +1,70 @@
|
|||
XFRM proc - /proc/net/xfrm_* files
|
||||
==================================
|
||||
Masahide NAKAMURA <nakam@linux-ipv6.org>
|
||||
|
||||
|
||||
Transformation Statistics
|
||||
-------------------------
|
||||
xfrm_proc is a statistics shown factor dropped by transformation
|
||||
for developer.
|
||||
It is a counter designed from current transformation source code
|
||||
and defined like linux private MIB.
|
||||
|
||||
Inbound statistics
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
XfrmInError:
|
||||
All errors which is not matched others
|
||||
XfrmInBufferError:
|
||||
No buffer is left
|
||||
XfrmInHdrError:
|
||||
Header error
|
||||
XfrmInNoStates:
|
||||
No state is found
|
||||
i.e. Either inbound SPI, address, or IPsec protocol at SA is wrong
|
||||
XfrmInStateProtoError:
|
||||
Transformation protocol specific error
|
||||
e.g. SA key is wrong
|
||||
XfrmInStateModeError:
|
||||
Transformation mode specific error
|
||||
XfrmInSeqOutOfWindow:
|
||||
Sequence out of window
|
||||
XfrmInStateExpired:
|
||||
State is expired
|
||||
XfrmInStateMismatch:
|
||||
State has mismatch option
|
||||
e.g. UDP encapsulation type is mismatch
|
||||
XfrmInStateInvalid:
|
||||
State is invalid
|
||||
XfrmInTmplMismatch:
|
||||
No matching template for states
|
||||
e.g. Inbound SAs are correct but SP rule is wrong
|
||||
XfrmInNoPols:
|
||||
No policy is found for states
|
||||
e.g. Inbound SAs are correct but no SP is found
|
||||
XfrmInPolBlock:
|
||||
Policy discards
|
||||
XfrmInPolError:
|
||||
Policy error
|
||||
|
||||
Outbound errors
|
||||
~~~~~~~~~~~~~~~
|
||||
XfrmOutError:
|
||||
All errors which is not matched others
|
||||
XfrmOutBundleGenError:
|
||||
Bundle generation error
|
||||
XfrmOutBundleCheckError:
|
||||
Bundle check error
|
||||
XfrmOutNoStates:
|
||||
No state is found
|
||||
XfrmOutStateProtoError:
|
||||
Transformation protocol specific error
|
||||
XfrmOutStateModeError:
|
||||
Transformation mode specific error
|
||||
XfrmOutStateExpired:
|
||||
State is expired
|
||||
XfrmOutPolBlock:
|
||||
Policy discards
|
||||
XfrmOutPolDead:
|
||||
Policy is dead
|
||||
XfrmOutPolError:
|
||||
Policy error
|
48
MAINTAINERS
48
MAINTAINERS
|
@ -646,6 +646,17 @@ M: ecashin@coraid.com
|
|||
W: http://www.coraid.com/support/linux
|
||||
S: Supported
|
||||
|
||||
ATHEROS ATH5K WIRELESS DRIVER
|
||||
P: Jiri Slaby
|
||||
M: jirislaby@gmail.com
|
||||
P: Nick Kossifidis
|
||||
M: mickflemm@gmail.com
|
||||
P: Luis R. Rodriguez
|
||||
M: mcgrof@gmail.com
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ath5k-devel@lists.ath5k.org
|
||||
S: Maintained
|
||||
|
||||
ATL1 ETHERNET DRIVER
|
||||
P: Jay Cliburn
|
||||
M: jcliburn@gmail.com
|
||||
|
@ -809,7 +820,7 @@ P: Stefano Brivio
|
|||
M: stefano.brivio@polimi.it
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://bcm43xx.berlios.de/
|
||||
S: Maintained
|
||||
S: Obsolete
|
||||
|
||||
BEFS FILE SYSTEM
|
||||
P: Sergey S. Kostyliov
|
||||
|
@ -982,6 +993,15 @@ M: corbet@lwn.net
|
|||
L: video4linux-list@redhat.com
|
||||
S: Maintained
|
||||
|
||||
CAN NETWORK LAYER
|
||||
P: Urs Thuermann
|
||||
M: urs.thuermann@volkswagen.de
|
||||
P: Oliver Hartkopp
|
||||
M: oliver.hartkopp@volkswagen.de
|
||||
L: socketcan-core@lists.berlios.de
|
||||
W: http://developer.berlios.de/projects/socketcan/
|
||||
S: Maintained
|
||||
|
||||
CALGARY x86-64 IOMMU
|
||||
P: Muli Ben-Yehuda
|
||||
M: muli@il.ibm.com
|
||||
|
@ -2027,10 +2047,12 @@ W: http://sourceforge.net/projects/e1000/
|
|||
S: Supported
|
||||
|
||||
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
|
||||
P: Yi Zhu
|
||||
P: Zhu Yi
|
||||
M: yi.zhu@intel.com
|
||||
P: James Ketrenos
|
||||
M: jketreno@linux.intel.com
|
||||
P: Reinette Chatre
|
||||
M: reinette.chatre@intel.com
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw2100-devel@lists.sourceforge.net
|
||||
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
|
||||
|
@ -2038,10 +2060,12 @@ W: http://ipw2100.sourceforge.net
|
|||
S: Supported
|
||||
|
||||
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
|
||||
P: Yi Zhu
|
||||
P: Zhu Yi
|
||||
M: yi.zhu@intel.com
|
||||
P: James Ketrenos
|
||||
M: jketreno@linux.intel.com
|
||||
P: Reinette Chatre
|
||||
M: reinette.chatre@intel.com
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw2100-devel@lists.sourceforge.net
|
||||
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
|
||||
|
@ -2051,6 +2075,8 @@ S: Supported
|
|||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
P: Zhu Yi
|
||||
M: yi.zhu@intel.com
|
||||
P: Reinette Chatre
|
||||
M: reinette.chatre@intel.com
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw3945-devel@lists.sourceforge.net
|
||||
W: http://intellinuxwireless.org
|
||||
|
@ -2482,6 +2508,16 @@ W: http://linuxwireless.org/
|
|||
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
||||
S: Maintained
|
||||
|
||||
MAC80211 PID RATE CONTROL
|
||||
P: Stefano Brivio
|
||||
M: stefano.brivio@polimi.it
|
||||
P: Mattias Nissler
|
||||
M: mattias.nissler@gmx.de
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
||||
S: Maintained
|
||||
|
||||
MACVLAN DRIVER
|
||||
P: Patrick McHardy
|
||||
M: kaber@trash.net
|
||||
|
@ -3183,6 +3219,12 @@ M: mporter@kernel.crashing.org
|
|||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
RDC R6040 FAST ETHERNET DRIVER
|
||||
P: Florian Fainelli
|
||||
M: florian.fainelli@telecomint.eu
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
READ-COPY UPDATE (RCU)
|
||||
P: Dipankar Sarma
|
||||
M: dipankar@in.ibm.com
|
||||
|
|
|
@ -497,11 +497,6 @@ simeth_interrupt(int irq, void *dev_id)
|
|||
{
|
||||
struct net_device *dev = dev_id;
|
||||
|
||||
if ( dev == NULL ) {
|
||||
printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* very simple loop because we get interrupts only when receiving
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o
|
||||
obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o
|
||||
obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
|
||||
obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
|
||||
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
|
||||
|
|
488
arch/powerpc/platforms/pasemi/dma_lib.c
Normal file
488
arch/powerpc/platforms/pasemi/dma_lib.c
Normal file
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2007 PA Semi, Inc
|
||||
*
|
||||
* Common functions for DMA access on PA Semi PWRficient
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/pasemi_dma.h>
|
||||
|
||||
#define MAX_TXCH 64
|
||||
#define MAX_RXCH 64
|
||||
|
||||
static struct pasdma_status *dma_status;
|
||||
|
||||
static void __iomem *iob_regs;
|
||||
static void __iomem *mac_regs[6];
|
||||
static void __iomem *dma_regs;
|
||||
|
||||
static int base_hw_irq;
|
||||
|
||||
static int num_txch, num_rxch;
|
||||
|
||||
static struct pci_dev *dma_pdev;
|
||||
|
||||
/* Bitmaps to handle allocation of channels */
|
||||
|
||||
static DECLARE_BITMAP(txch_free, MAX_TXCH);
|
||||
static DECLARE_BITMAP(rxch_free, MAX_RXCH);
|
||||
|
||||
/* pasemi_read_iob_reg - read IOB register
|
||||
* @reg: Register to read (offset into PCI CFG space)
|
||||
*/
|
||||
unsigned int pasemi_read_iob_reg(unsigned int reg)
|
||||
{
|
||||
return in_le32(iob_regs+reg);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_read_iob_reg);
|
||||
|
||||
/* pasemi_write_iob_reg - write IOB register
|
||||
* @reg: Register to write to (offset into PCI CFG space)
|
||||
* @val: Value to write
|
||||
*/
|
||||
void pasemi_write_iob_reg(unsigned int reg, unsigned int val)
|
||||
{
|
||||
out_le32(iob_regs+reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_write_iob_reg);
|
||||
|
||||
/* pasemi_read_mac_reg - read MAC register
|
||||
* @intf: MAC interface
|
||||
* @reg: Register to read (offset into PCI CFG space)
|
||||
*/
|
||||
unsigned int pasemi_read_mac_reg(int intf, unsigned int reg)
|
||||
{
|
||||
return in_le32(mac_regs[intf]+reg);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_read_mac_reg);
|
||||
|
||||
/* pasemi_write_mac_reg - write MAC register
|
||||
* @intf: MAC interface
|
||||
* @reg: Register to write to (offset into PCI CFG space)
|
||||
* @val: Value to write
|
||||
*/
|
||||
void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val)
|
||||
{
|
||||
out_le32(mac_regs[intf]+reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_write_mac_reg);
|
||||
|
||||
/* pasemi_read_dma_reg - read DMA register
|
||||
* @reg: Register to read (offset into PCI CFG space)
|
||||
*/
|
||||
unsigned int pasemi_read_dma_reg(unsigned int reg)
|
||||
{
|
||||
return in_le32(dma_regs+reg);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_read_dma_reg);
|
||||
|
||||
/* pasemi_write_dma_reg - write DMA register
|
||||
* @reg: Register to write to (offset into PCI CFG space)
|
||||
* @val: Value to write
|
||||
*/
|
||||
void pasemi_write_dma_reg(unsigned int reg, unsigned int val)
|
||||
{
|
||||
out_le32(dma_regs+reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_write_dma_reg);
|
||||
|
||||
static int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type)
|
||||
{
|
||||
int bit;
|
||||
int start, limit;
|
||||
|
||||
switch (type & (TXCHAN_EVT0|TXCHAN_EVT1)) {
|
||||
case TXCHAN_EVT0:
|
||||
start = 0;
|
||||
limit = 10;
|
||||
break;
|
||||
case TXCHAN_EVT1:
|
||||
start = 10;
|
||||
limit = MAX_TXCH;
|
||||
break;
|
||||
default:
|
||||
start = 0;
|
||||
limit = MAX_TXCH;
|
||||
break;
|
||||
}
|
||||
retry:
|
||||
bit = find_next_bit(txch_free, MAX_TXCH, start);
|
||||
if (bit >= limit)
|
||||
return -ENOSPC;
|
||||
if (!test_and_clear_bit(bit, txch_free))
|
||||
goto retry;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
static void pasemi_free_tx_chan(int chan)
|
||||
{
|
||||
BUG_ON(test_bit(chan, txch_free));
|
||||
set_bit(chan, txch_free);
|
||||
}
|
||||
|
||||
static int pasemi_alloc_rx_chan(void)
|
||||
{
|
||||
int bit;
|
||||
retry:
|
||||
bit = find_first_bit(rxch_free, MAX_RXCH);
|
||||
if (bit >= MAX_TXCH)
|
||||
return -ENOSPC;
|
||||
if (!test_and_clear_bit(bit, rxch_free))
|
||||
goto retry;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
static void pasemi_free_rx_chan(int chan)
|
||||
{
|
||||
BUG_ON(test_bit(chan, rxch_free));
|
||||
set_bit(chan, rxch_free);
|
||||
}
|
||||
|
||||
/* pasemi_dma_alloc_chan - Allocate a DMA channel
|
||||
* @type: Type of channel to allocate
|
||||
* @total_size: Total size of structure to allocate (to allow for more
|
||||
* room behind the structure to be used by the client)
|
||||
* @offset: Offset in bytes from start of the total structure to the beginning
|
||||
* of struct pasemi_dmachan. Needed when struct pasemi_dmachan is
|
||||
* not the first member of the client structure.
|
||||
*
|
||||
* pasemi_dma_alloc_chan allocates a DMA channel for use by a client. The
|
||||
* type argument specifies whether it's a RX or TX channel, and in the case
|
||||
* of TX channels which group it needs to belong to (if any).
|
||||
*
|
||||
* Returns a pointer to the total structure allocated on success, NULL
|
||||
* on failure.
|
||||
*/
|
||||
void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
|
||||
int total_size, int offset)
|
||||
{
|
||||
void *buf;
|
||||
struct pasemi_dmachan *chan;
|
||||
int chno;
|
||||
|
||||
BUG_ON(total_size < sizeof(struct pasemi_dmachan));
|
||||
|
||||
buf = kzalloc(total_size, GFP_KERNEL);
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
chan = buf + offset;
|
||||
|
||||
chan->priv = buf;
|
||||
|
||||
switch (type & (TXCHAN|RXCHAN)) {
|
||||
case RXCHAN:
|
||||
chno = pasemi_alloc_rx_chan();
|
||||
chan->chno = chno;
|
||||
chan->irq = irq_create_mapping(NULL,
|
||||
base_hw_irq + num_txch + chno);
|
||||
chan->status = &dma_status->rx_sta[chno];
|
||||
break;
|
||||
case TXCHAN:
|
||||
chno = pasemi_alloc_tx_chan(type);
|
||||
chan->chno = chno;
|
||||
chan->irq = irq_create_mapping(NULL, base_hw_irq + chno);
|
||||
chan->status = &dma_status->tx_sta[chno];
|
||||
break;
|
||||
}
|
||||
|
||||
chan->chan_type = type;
|
||||
|
||||
return chan;
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_alloc_chan);
|
||||
|
||||
/* pasemi_dma_free_chan - Free a previously allocated channel
|
||||
* @chan: Channel to free
|
||||
*
|
||||
* Frees a previously allocated channel. It will also deallocate any
|
||||
* descriptor ring associated with the channel, if allocated.
|
||||
*/
|
||||
void pasemi_dma_free_chan(struct pasemi_dmachan *chan)
|
||||
{
|
||||
if (chan->ring_virt)
|
||||
pasemi_dma_free_ring(chan);
|
||||
|
||||
switch (chan->chan_type & (RXCHAN|TXCHAN)) {
|
||||
case RXCHAN:
|
||||
pasemi_free_rx_chan(chan->chno);
|
||||
break;
|
||||
case TXCHAN:
|
||||
pasemi_free_tx_chan(chan->chno);
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(chan->priv);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_free_chan);
|
||||
|
||||
/* pasemi_dma_alloc_ring - Allocate descriptor ring for a channel
|
||||
* @chan: Channel for which to allocate
|
||||
* @ring_size: Ring size in 64-bit (8-byte) words
|
||||
*
|
||||
* Allocate a descriptor ring for a channel. Returns 0 on success, errno
|
||||
* on failure. The passed in struct pasemi_dmachan is updated with the
|
||||
* virtual and DMA addresses of the ring.
|
||||
*/
|
||||
int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
|
||||
{
|
||||
BUG_ON(chan->ring_virt);
|
||||
|
||||
chan->ring_size = ring_size;
|
||||
|
||||
chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
|
||||
ring_size * sizeof(u64),
|
||||
&chan->ring_dma, GFP_KERNEL);
|
||||
|
||||
if (!chan->ring_virt)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(chan->ring_virt, 0, ring_size * sizeof(u64));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_alloc_ring);
|
||||
|
||||
/* pasemi_dma_free_ring - Free an allocated descriptor ring for a channel
|
||||
* @chan: Channel for which to free the descriptor ring
|
||||
*
|
||||
* Frees a previously allocated descriptor ring for a channel.
|
||||
*/
|
||||
void pasemi_dma_free_ring(struct pasemi_dmachan *chan)
|
||||
{
|
||||
BUG_ON(!chan->ring_virt);
|
||||
|
||||
dma_free_coherent(&dma_pdev->dev, chan->ring_size * sizeof(u64),
|
||||
chan->ring_virt, chan->ring_dma);
|
||||
chan->ring_virt = NULL;
|
||||
chan->ring_size = 0;
|
||||
chan->ring_dma = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_free_ring);
|
||||
|
||||
/* pasemi_dma_start_chan - Start a DMA channel
|
||||
* @chan: Channel to start
|
||||
* @cmdsta: Additional CCMDSTA/TCMDSTA bits to write
|
||||
*
|
||||
* Enables (starts) a DMA channel with optional additional arguments.
|
||||
*/
|
||||
void pasemi_dma_start_chan(const struct pasemi_dmachan *chan, const u32 cmdsta)
|
||||
{
|
||||
if (chan->chan_type == RXCHAN)
|
||||
pasemi_write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno),
|
||||
cmdsta | PAS_DMA_RXCHAN_CCMDSTA_EN);
|
||||
else
|
||||
pasemi_write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno),
|
||||
cmdsta | PAS_DMA_TXCHAN_TCMDSTA_EN);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_start_chan);
|
||||
|
||||
/* pasemi_dma_stop_chan - Stop a DMA channel
|
||||
* @chan: Channel to stop
|
||||
*
|
||||
* Stops (disables) a DMA channel. This is done by setting the ST bit in the
|
||||
* CMDSTA register and waiting on the ACT (active) bit to clear, then
|
||||
* finally disabling the whole channel.
|
||||
*
|
||||
* This function will only try for a short while for the channel to stop, if
|
||||
* it doesn't it will return failure.
|
||||
*
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
#define MAX_RETRIES 5000
|
||||
int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan)
|
||||
{
|
||||
int reg, retries;
|
||||
u32 sta;
|
||||
|
||||
if (chan->chan_type == RXCHAN) {
|
||||
reg = PAS_DMA_RXCHAN_CCMDSTA(chan->chno);
|
||||
pasemi_write_dma_reg(reg, PAS_DMA_RXCHAN_CCMDSTA_ST);
|
||||
for (retries = 0; retries < MAX_RETRIES; retries++) {
|
||||
sta = pasemi_read_dma_reg(reg);
|
||||
if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
|
||||
pasemi_write_dma_reg(reg, 0);
|
||||
return 1;
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
} else {
|
||||
reg = PAS_DMA_TXCHAN_TCMDSTA(chan->chno);
|
||||
pasemi_write_dma_reg(reg, PAS_DMA_TXCHAN_TCMDSTA_ST);
|
||||
for (retries = 0; retries < MAX_RETRIES; retries++) {
|
||||
sta = pasemi_read_dma_reg(reg);
|
||||
if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
|
||||
pasemi_write_dma_reg(reg, 0);
|
||||
return 1;
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_stop_chan);
|
||||
|
||||
/* pasemi_dma_alloc_buf - Allocate a buffer to use for DMA
|
||||
* @chan: Channel to allocate for
|
||||
* @size: Size of buffer in bytes
|
||||
* @handle: DMA handle
|
||||
*
|
||||
* Allocate a buffer to be used by the DMA engine for read/write,
|
||||
* similar to dma_alloc_coherent().
|
||||
*
|
||||
* Returns the virtual address of the buffer, or NULL in case of failure.
|
||||
*/
|
||||
void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
|
||||
dma_addr_t *handle)
|
||||
{
|
||||
return dma_alloc_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_alloc_buf);
|
||||
|
||||
/* pasemi_dma_free_buf - Free a buffer used for DMA
|
||||
* @chan: Channel the buffer was allocated for
|
||||
* @size: Size of buffer in bytes
|
||||
* @handle: DMA handle
|
||||
*
|
||||
* Frees a previously allocated buffer.
|
||||
*/
|
||||
void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
|
||||
dma_addr_t *handle)
|
||||
{
|
||||
dma_free_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_free_buf);
|
||||
|
||||
static void *map_onedev(struct pci_dev *p, int index)
|
||||
{
|
||||
struct device_node *dn;
|
||||
void __iomem *ret;
|
||||
|
||||
dn = pci_device_to_OF_node(p);
|
||||
if (!dn)
|
||||
goto fallback;
|
||||
|
||||
ret = of_iomap(dn, index);
|
||||
if (!ret)
|
||||
goto fallback;
|
||||
|
||||
return ret;
|
||||
fallback:
|
||||
/* This is hardcoded and ugly, but we have some firmware versions
|
||||
* that don't provide the register space in the device tree. Luckily
|
||||
* they are at well-known locations so we can just do the math here.
|
||||
*/
|
||||
return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
|
||||
}
|
||||
|
||||
/* pasemi_dma_init - Initialize the PA Semi DMA library
|
||||
*
|
||||
* This function initializes the DMA library. It must be called before
|
||||
* any other function in the library.
|
||||
*
|
||||
* Returns 0 on success, errno on failure.
|
||||
*/
|
||||
int pasemi_dma_init(void)
|
||||
{
|
||||
static spinlock_t init_lock = SPIN_LOCK_UNLOCKED;
|
||||
struct pci_dev *iob_pdev;
|
||||
struct pci_dev *pdev;
|
||||
struct resource res;
|
||||
struct device_node *dn;
|
||||
int i, intf, err = 0;
|
||||
u32 tmp;
|
||||
|
||||
if (!machine_is(pasemi))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock(&init_lock);
|
||||
|
||||
/* Make sure we haven't already initialized */
|
||||
if (dma_pdev)
|
||||
goto out;
|
||||
|
||||
iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
|
||||
if (!iob_pdev) {
|
||||
BUG();
|
||||
printk(KERN_WARNING "Can't find I/O Bridge\n");
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
iob_regs = map_onedev(iob_pdev, 0);
|
||||
|
||||
dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
|
||||
if (!dma_pdev) {
|
||||
BUG();
|
||||
printk(KERN_WARNING "Can't find DMA controller\n");
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
dma_regs = map_onedev(dma_pdev, 0);
|
||||
base_hw_irq = virq_to_hw(dma_pdev->irq);
|
||||
|
||||
pci_read_config_dword(dma_pdev, PAS_DMA_CAP_TXCH, &tmp);
|
||||
num_txch = (tmp & PAS_DMA_CAP_TXCH_TCHN_M) >> PAS_DMA_CAP_TXCH_TCHN_S;
|
||||
|
||||
pci_read_config_dword(dma_pdev, PAS_DMA_CAP_RXCH, &tmp);
|
||||
num_rxch = (tmp & PAS_DMA_CAP_RXCH_RCHN_M) >> PAS_DMA_CAP_RXCH_RCHN_S;
|
||||
|
||||
intf = 0;
|
||||
for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, NULL);
|
||||
pdev;
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, pdev))
|
||||
mac_regs[intf++] = map_onedev(pdev, 0);
|
||||
|
||||
pci_dev_put(pdev);
|
||||
|
||||
for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, NULL);
|
||||
pdev;
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, pdev))
|
||||
mac_regs[intf++] = map_onedev(pdev, 0);
|
||||
|
||||
pci_dev_put(pdev);
|
||||
|
||||
dn = pci_device_to_OF_node(iob_pdev);
|
||||
if (dn)
|
||||
err = of_address_to_resource(dn, 1, &res);
|
||||
if (!dn || err) {
|
||||
/* Fallback for old firmware */
|
||||
res.start = 0xfd800000;
|
||||
res.end = res.start + 0x1000;
|
||||
}
|
||||
dma_status = __ioremap(res.start, res.end-res.start, 0);
|
||||
pci_dev_put(iob_pdev);
|
||||
|
||||
for (i = 0; i < MAX_TXCH; i++)
|
||||
__set_bit(i, txch_free);
|
||||
|
||||
for (i = 0; i < MAX_RXCH; i++)
|
||||
__set_bit(i, rxch_free);
|
||||
|
||||
printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
|
||||
"(%d tx, %d rx channels)\n", num_txch, num_rxch);
|
||||
|
||||
out:
|
||||
spin_unlock(&init_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(pasemi_dma_init);
|
|
@ -9,6 +9,7 @@ extern void __devinit pas_pci_dma_dev_setup(struct pci_dev *dev);
|
|||
extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset);
|
||||
|
||||
extern void __init alloc_iobmap_l2(void);
|
||||
extern void __init pasemi_map_registers(void);
|
||||
|
||||
/* Power savings modes, implemented in asm */
|
||||
extern void idle_spin(void);
|
||||
|
|
|
@ -272,7 +272,7 @@ scc_enet_timeout(struct net_device *dev)
|
|||
* This is called from the CPM handler, not the MPC core interrupt.
|
||||
*/
|
||||
static irqreturn_t
|
||||
scc_enet_interrupt(int irq, void * dev_id)
|
||||
scc_enet_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
volatile struct scc_enet_private *cep;
|
||||
|
@ -280,7 +280,7 @@ scc_enet_interrupt(int irq, void * dev_id)
|
|||
ushort int_events;
|
||||
int must_restart;
|
||||
|
||||
cep = (struct scc_enet_private *)dev->priv;
|
||||
cep = dev->priv;
|
||||
|
||||
/* Get the interrupt events that caused us to be here.
|
||||
*/
|
||||
|
|
|
@ -524,7 +524,7 @@ fcc_enet_timeout(struct net_device *dev)
|
|||
|
||||
/* The interrupt handler. */
|
||||
static irqreturn_t
|
||||
fcc_enet_interrupt(int irq, void * dev_id)
|
||||
fcc_enet_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
volatile struct fcc_enet_private *cep;
|
||||
|
@ -532,7 +532,7 @@ fcc_enet_interrupt(int irq, void * dev_id)
|
|||
ushort int_events;
|
||||
int must_restart;
|
||||
|
||||
cep = (struct fcc_enet_private *)dev->priv;
|
||||
cep = dev->priv;
|
||||
|
||||
/* Get the interrupt events that caused us to be here.
|
||||
*/
|
||||
|
|
|
@ -2163,7 +2163,6 @@ static int __devinit amb_init (amb_dev * dev)
|
|||
static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev)
|
||||
{
|
||||
unsigned char pool;
|
||||
memset (dev, 0, sizeof(amb_dev));
|
||||
|
||||
// set up known dev items straight away
|
||||
dev->pci_dev = pci_dev;
|
||||
|
@ -2253,7 +2252,7 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
|
|||
goto out_disable;
|
||||
}
|
||||
|
||||
dev = kmalloc (sizeof(amb_dev), GFP_KERNEL);
|
||||
dev = kzalloc(sizeof(amb_dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
PRINTK (KERN_ERR, "out of memory!");
|
||||
err = -ENOMEM;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */
|
||||
|
||||
/*
|
||||
|
||||
he.c
|
||||
|
@ -99,10 +97,6 @@
|
|||
#define HPRINTK(fmt,args...) do { } while (0)
|
||||
#endif /* HE_DEBUG */
|
||||
|
||||
/* version definition */
|
||||
|
||||
static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $";
|
||||
|
||||
/* declarations */
|
||||
|
||||
static int he_open(struct atm_vcc *vcc);
|
||||
|
@ -366,7 +360,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
|
|||
struct he_dev *he_dev = NULL;
|
||||
int err = 0;
|
||||
|
||||
printk(KERN_INFO "he: %s\n", version);
|
||||
printk(KERN_INFO "ATM he driver\n");
|
||||
|
||||
if (pci_enable_device(pci_dev))
|
||||
return -EIO;
|
||||
|
@ -1643,6 +1637,8 @@ he_stop(struct he_dev *he_dev)
|
|||
|
||||
if (he_dev->rbpl_base) {
|
||||
#ifdef USE_RBPL_POOL
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
|
||||
void *cpuaddr = he_dev->rbpl_virt[i].virt;
|
||||
dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
|
||||
|
@ -1665,6 +1661,8 @@ he_stop(struct he_dev *he_dev)
|
|||
#ifdef USE_RBPS
|
||||
if (he_dev->rbps_base) {
|
||||
#ifdef USE_RBPS_POOL
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
|
||||
void *cpuaddr = he_dev->rbps_virt[i].virt;
|
||||
dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
|
||||
|
@ -2933,7 +2931,7 @@ he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
|
|||
|
||||
left = *pos;
|
||||
if (!left--)
|
||||
return sprintf(page, "%s\n", version);
|
||||
return sprintf(page, "ATM he driver\n");
|
||||
|
||||
if (!left--)
|
||||
return sprintf(page, "%s%s\n\n",
|
||||
|
|
|
@ -104,7 +104,6 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
cbq->nls = dev->nls;
|
||||
cbq->seq = 0;
|
||||
cbq->group = cbq->id.id.idx;
|
||||
|
||||
|
@ -146,7 +145,6 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
|
|||
spin_lock_init(&dev->queue_lock);
|
||||
|
||||
dev->nls = nls;
|
||||
dev->netlink_groups = 0;
|
||||
|
||||
dev->cn_queue = create_workqueue(dev->name);
|
||||
if (!dev->cn_queue) {
|
||||
|
|
|
@ -88,6 +88,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
|
|||
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
|
||||
found = 1;
|
||||
group = __cbq->group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&dev->cbdev->queue_lock);
|
||||
|
@ -180,34 +181,15 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skb receive helper - checks skb and msg size and calls callback
|
||||
* helper.
|
||||
*/
|
||||
static int __cn_rx_skb(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
u32 pid, uid, seq, group;
|
||||
struct cn_msg *msg;
|
||||
|
||||
pid = NETLINK_CREDS(skb)->pid;
|
||||
uid = NETLINK_CREDS(skb)->uid;
|
||||
seq = nlh->nlmsg_seq;
|
||||
group = NETLINK_CB((skb)).dst_group;
|
||||
msg = NLMSG_DATA(nlh);
|
||||
|
||||
return cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Main netlink receiving function.
|
||||
*
|
||||
* It checks skb and netlink header sizes and calls the skb receive
|
||||
* helper with a shared skb.
|
||||
* It checks skb, netlink header and msg sizes, and calls callback helper.
|
||||
*/
|
||||
static void cn_rx_skb(struct sk_buff *__skb)
|
||||
{
|
||||
struct cn_msg *msg;
|
||||
struct nlmsghdr *nlh;
|
||||
u32 len;
|
||||
int err;
|
||||
struct sk_buff *skb;
|
||||
|
||||
|
@ -223,11 +205,8 @@ static void cn_rx_skb(struct sk_buff *__skb)
|
|||
return;
|
||||
}
|
||||
|
||||
len = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
if (len > skb->len)
|
||||
len = skb->len;
|
||||
|
||||
err = __cn_rx_skb(skb, nlh);
|
||||
msg = NLMSG_DATA(nlh);
|
||||
err = cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
|
||||
if (err < 0)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
@ -441,8 +420,7 @@ static int __devinit cn_init(void)
|
|||
|
||||
dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
|
||||
if (!dev->cbdev) {
|
||||
if (dev->nls->sk_socket)
|
||||
sock_release(dev->nls->sk_socket);
|
||||
netlink_kernel_release(dev->nls);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -452,8 +430,7 @@ static int __devinit cn_init(void)
|
|||
if (err) {
|
||||
cn_already_initialized = 0;
|
||||
cn_queue_free_dev(dev->cbdev);
|
||||
if (dev->nls->sk_socket)
|
||||
sock_release(dev->nls->sk_socket);
|
||||
netlink_kernel_release(dev->nls);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -468,8 +445,7 @@ static void __devexit cn_fini(void)
|
|||
|
||||
cn_del_callback(&dev->id);
|
||||
cn_queue_free_dev(dev->cbdev);
|
||||
if (dev->nls->sk_socket)
|
||||
sock_release(dev->nls->sk_socket);
|
||||
netlink_kernel_release(dev->nls);
|
||||
}
|
||||
|
||||
subsys_initcall(cn_init);
|
||||
|
|
|
@ -110,7 +110,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
|
|||
__be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
|
||||
int ret;
|
||||
|
||||
dev = ip_dev_find(ip);
|
||||
dev = ip_dev_find(&init_net, ip);
|
||||
if (!dev)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
|
@ -158,7 +158,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
|
|||
|
||||
memset(&fl, 0, sizeof fl);
|
||||
fl.nl_u.ip4_u.daddr = dst_ip;
|
||||
if (ip_route_output_key(&rt, &fl))
|
||||
if (ip_route_output_key(&init_net, &rt, &fl))
|
||||
return;
|
||||
|
||||
neigh_event_send(rt->u.dst.neighbour, NULL);
|
||||
|
@ -179,7 +179,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
|
|||
memset(&fl, 0, sizeof fl);
|
||||
fl.nl_u.ip4_u.daddr = dst_ip;
|
||||
fl.nl_u.ip4_u.saddr = src_ip;
|
||||
ret = ip_route_output_key(&rt, &fl);
|
||||
ret = ip_route_output_key(&init_net, &rt, &fl);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
@ -261,15 +261,15 @@ static int addr_resolve_local(struct sockaddr_in *src_in,
|
|||
__be32 dst_ip = dst_in->sin_addr.s_addr;
|
||||
int ret;
|
||||
|
||||
dev = ip_dev_find(dst_ip);
|
||||
dev = ip_dev_find(&init_net, dst_ip);
|
||||
if (!dev)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (ZERONET(src_ip)) {
|
||||
if (ipv4_is_zeronet(src_ip)) {
|
||||
src_in->sin_family = dst_in->sin_family;
|
||||
src_in->sin_addr.s_addr = dst_ip;
|
||||
ret = rdma_copy_addr(addr, dev, dev->dev_addr);
|
||||
} else if (LOOPBACK(src_ip)) {
|
||||
} else if (ipv4_is_loopback(src_ip)) {
|
||||
ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
|
||||
if (!ret)
|
||||
memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
|
||||
|
|
|
@ -630,7 +630,8 @@ static inline int cma_zero_addr(struct sockaddr *addr)
|
|||
struct in6_addr *ip6;
|
||||
|
||||
if (addr->sa_family == AF_INET)
|
||||
return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
|
||||
return ipv4_is_zeronet(
|
||||
((struct sockaddr_in *)addr)->sin_addr.s_addr);
|
||||
else {
|
||||
ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
|
||||
return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
|
||||
|
@ -640,7 +641,7 @@ static inline int cma_zero_addr(struct sockaddr *addr)
|
|||
|
||||
static inline int cma_loopback_addr(struct sockaddr *addr)
|
||||
{
|
||||
return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
|
||||
return ipv4_is_loopback(((struct sockaddr_in *) addr)->sin_addr.s_addr);
|
||||
}
|
||||
|
||||
static inline int cma_any_addr(struct sockaddr *addr)
|
||||
|
@ -1288,7 +1289,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
|
|||
atomic_inc(&conn_id->dev_remove);
|
||||
conn_id->state = CMA_CONNECT;
|
||||
|
||||
dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr);
|
||||
dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
|
||||
if (!dev) {
|
||||
ret = -EADDRNOTAVAIL;
|
||||
cma_enable_remove(conn_id);
|
||||
|
|
|
@ -332,7 +332,7 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
|
|||
}
|
||||
};
|
||||
|
||||
if (ip_route_output_flow(&rt, &fl, NULL, 0))
|
||||
if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
|
||||
return NULL;
|
||||
return rt;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
Annapolis MD 21403
|
||||
|
||||
Fixed (again!) the missing interrupt locking on TX/RX shifting.
|
||||
Alan Cox <Alan.Cox@linux.org>
|
||||
Alan Cox <Alan.Cox@linux.org>
|
||||
|
||||
Removed calls to init_etherdev since they are no longer needed, and
|
||||
cleaned up modularization just a bit. The driver still allows only
|
||||
|
@ -29,16 +29,16 @@
|
|||
the board. Now getting 150K/second FTP with a 3c501 card. Still playing
|
||||
with a TX-TX optimisation to see if we can touch 180-200K/second as seems
|
||||
theoretically maximum.
|
||||
19950402 Alan Cox <Alan.Cox@linux.org>
|
||||
19950402 Alan Cox <Alan.Cox@linux.org>
|
||||
|
||||
Cleaned up for 2.3.x because we broke SMP now.
|
||||
20000208 Alan Cox <alan@redhat.com>
|
||||
20000208 Alan Cox <alan@redhat.com>
|
||||
|
||||
Check up pass for 2.5. Nothing significant changed
|
||||
20021009 Alan Cox <alan@redhat.com>
|
||||
20021009 Alan Cox <alan@redhat.com>
|
||||
|
||||
Fixed zero fill corner case
|
||||
20030104 Alan Cox <alan@redhat.com>
|
||||
20030104 Alan Cox <alan@redhat.com>
|
||||
|
||||
|
||||
For the avoidance of doubt the "preferred form" of this code is one which
|
||||
|
@ -139,8 +139,8 @@ static const char version[] =
|
|||
* The boilerplate probe code.
|
||||
*/
|
||||
|
||||
static int io=0x280;
|
||||
static int irq=5;
|
||||
static int io = 0x280;
|
||||
static int irq = 5;
|
||||
static int mem_start;
|
||||
|
||||
/**
|
||||
|
@ -229,8 +229,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
|
|||
* Read the station address PROM data from the special port.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
for (i = 0; i < 6; i++) {
|
||||
outw(i, ioaddr + EL1_DATAPTR);
|
||||
station_addr[i] = inb(ioaddr + EL1_SAPROM);
|
||||
}
|
||||
|
@ -240,28 +239,24 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
|
|||
*/
|
||||
|
||||
if (station_addr[0] == 0x02 && station_addr[1] == 0x60
|
||||
&& station_addr[2] == 0x8c)
|
||||
{
|
||||
&& station_addr[2] == 0x8c)
|
||||
mname = "3c501";
|
||||
} else if (station_addr[0] == 0x00 && station_addr[1] == 0x80
|
||||
&& station_addr[2] == 0xC8)
|
||||
{
|
||||
else if (station_addr[0] == 0x00 && station_addr[1] == 0x80
|
||||
&& station_addr[2] == 0xC8)
|
||||
mname = "NP943";
|
||||
}
|
||||
else {
|
||||
else {
|
||||
release_region(ioaddr, EL1_IO_EXTENT);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* We auto-IRQ by shutting off the interrupt line and letting it float
|
||||
* high.
|
||||
* We auto-IRQ by shutting off the interrupt line and letting it
|
||||
* float high.
|
||||
*/
|
||||
|
||||
dev->irq = irq;
|
||||
|
||||
if (dev->irq < 2)
|
||||
{
|
||||
if (dev->irq < 2) {
|
||||
unsigned long irq_mask;
|
||||
|
||||
irq_mask = probe_irq_on();
|
||||
|
@ -274,8 +269,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
|
|||
mdelay(20);
|
||||
autoirq = probe_irq_off(irq_mask);
|
||||
|
||||
if (autoirq == 0)
|
||||
{
|
||||
if (autoirq == 0) {
|
||||
printk(KERN_WARNING "%s probe at %#x failed to detect IRQ line.\n",
|
||||
mname, ioaddr);
|
||||
release_region(ioaddr, EL1_IO_EXTENT);
|
||||
|
@ -292,7 +286,8 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
|
|||
if (autoirq)
|
||||
dev->irq = autoirq;
|
||||
|
||||
printk(KERN_INFO "%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr,
|
||||
printk(KERN_INFO "%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
|
||||
dev->name, mname, dev->base_addr,
|
||||
autoirq ? "auto":"assigned ", dev->irq);
|
||||
|
||||
#ifdef CONFIG_IP_MULTICAST
|
||||
|
@ -343,7 +338,8 @@ static int el_open(struct net_device *dev)
|
|||
if (el_debug > 2)
|
||||
printk(KERN_DEBUG "%s: Doing el_open()...", dev->name);
|
||||
|
||||
if ((retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev)))
|
||||
retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
|
@ -371,8 +367,9 @@ static void el_timeout(struct net_device *dev)
|
|||
int ioaddr = dev->base_addr;
|
||||
|
||||
if (el_debug)
|
||||
printk (KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
|
||||
dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
|
||||
printk(KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
|
||||
dev->name, inb(TX_STATUS),
|
||||
inb(AX_STATUS), inb(RX_STATUS));
|
||||
dev->stats.tx_errors++;
|
||||
outb(TX_NORM, TX_CMD);
|
||||
outb(RX_NORM, RX_CMD);
|
||||
|
@ -425,8 +422,7 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
int len = skb->len;
|
||||
int pad = 0;
|
||||
int gp_start;
|
||||
|
@ -435,10 +431,10 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (len < ETH_ZLEN)
|
||||
pad = ETH_ZLEN - len;
|
||||
|
||||
gp_start = 0x800 - ( len + pad );
|
||||
gp_start = 0x800 - (len + pad);
|
||||
|
||||
lp->tx_pkt_start = gp_start;
|
||||
lp->collisions = 0;
|
||||
lp->collisions = 0;
|
||||
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
|
@ -455,37 +451,42 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
lp->txing = 1;
|
||||
|
||||
/*
|
||||
* Turn interrupts back on while we spend a pleasant afternoon
|
||||
* loading bytes into the board
|
||||
* Turn interrupts back on while we spend a pleasant
|
||||
* afternoon loading bytes into the board
|
||||
*/
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
||||
outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */
|
||||
outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */
|
||||
outsb(DATAPORT,buf,len); /* load buffer (usual thing each byte increments the pointer) */
|
||||
/* Set rx packet area to 0. */
|
||||
outw(0x00, RX_BUF_CLR);
|
||||
/* aim - packet will be loaded into buffer start */
|
||||
outw(gp_start, GP_LOW);
|
||||
/* load buffer (usual thing each byte increments the pointer) */
|
||||
outsb(DATAPORT, buf, len);
|
||||
if (pad) {
|
||||
while(pad--) /* Zero fill buffer tail */
|
||||
while (pad--) /* Zero fill buffer tail */
|
||||
outb(0, DATAPORT);
|
||||
}
|
||||
outw(gp_start, GP_LOW); /* the board reuses the same register */
|
||||
/* the board reuses the same register */
|
||||
outw(gp_start, GP_LOW);
|
||||
|
||||
if(lp->loading != 2)
|
||||
{
|
||||
outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */
|
||||
lp->loading=0;
|
||||
if (lp->loading != 2) {
|
||||
/* fire ... Trigger xmit. */
|
||||
outb(AX_XMIT, AX_CMD);
|
||||
lp->loading = 0;
|
||||
dev->trans_start = jiffies;
|
||||
if (el_debug > 2)
|
||||
printk(KERN_DEBUG " queued xmit.\n");
|
||||
dev_kfree_skb (skb);
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
/* A receive upset our load, despite our best efforts */
|
||||
if(el_debug>2)
|
||||
printk(KERN_DEBUG "%s: burped during tx load.\n", dev->name);
|
||||
if (el_debug > 2)
|
||||
printk(KERN_DEBUG "%s: burped during tx load.\n",
|
||||
dev->name);
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
}
|
||||
while(1);
|
||||
while (1);
|
||||
|
||||
}
|
||||
|
||||
|
@ -534,64 +535,59 @@ static irqreturn_t el_interrupt(int irq, void *dev_id)
|
|||
*/
|
||||
|
||||
if (el_debug > 3)
|
||||
printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x", dev->name, axsr);
|
||||
printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x",
|
||||
dev->name, axsr);
|
||||
|
||||
if(lp->loading==1 && !lp->txing)
|
||||
printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n",
|
||||
dev->name);
|
||||
|
||||
if (lp->txing)
|
||||
{
|
||||
|
||||
/*
|
||||
* Board in transmit mode. May be loading. If we are
|
||||
* loading we shouldn't have got this.
|
||||
*/
|
||||
if (lp->loading == 1 && !lp->txing)
|
||||
printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n",
|
||||
dev->name);
|
||||
|
||||
if (lp->txing) {
|
||||
/*
|
||||
* Board in transmit mode. May be loading. If we are
|
||||
* loading we shouldn't have got this.
|
||||
*/
|
||||
int txsr = inb(TX_STATUS);
|
||||
|
||||
if(lp->loading==1)
|
||||
{
|
||||
if(el_debug > 2)
|
||||
{
|
||||
printk(KERN_DEBUG "%s: Interrupt while loading [", dev->name);
|
||||
printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW));
|
||||
if (lp->loading == 1) {
|
||||
if (el_debug > 2) {
|
||||
printk(KERN_DEBUG "%s: Interrupt while loading [",
|
||||
dev->name);
|
||||
printk(" txsr=%02x gp=%04x rp=%04x]\n",
|
||||
txsr, inw(GP_LOW), inw(RX_LOW));
|
||||
}
|
||||
lp->loading=2; /* Force a reload */
|
||||
/* Force a reload */
|
||||
lp->loading = 2;
|
||||
spin_unlock(&lp->lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (el_debug > 6)
|
||||
printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW));
|
||||
printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x",
|
||||
txsr, inw(GP_LOW), inw(RX_LOW));
|
||||
|
||||
if ((axsr & 0x80) && (txsr & TX_READY) == 0)
|
||||
{
|
||||
if ((axsr & 0x80) && (txsr & TX_READY) == 0) {
|
||||
/*
|
||||
* FIXME: is there a logic to whether to keep on trying or
|
||||
* reset immediately ?
|
||||
* FIXME: is there a logic to whether to keep
|
||||
* on trying or reset immediately ?
|
||||
*/
|
||||
if(el_debug>1)
|
||||
printk(KERN_DEBUG "%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"
|
||||
" gp=%03x rp=%03x.\n", dev->name, txsr, axsr,
|
||||
inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
|
||||
if (el_debug > 1)
|
||||
printk(KERN_DEBUG "%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n",
|
||||
dev->name, txsr, axsr,
|
||||
inw(ioaddr + EL1_DATAPTR),
|
||||
inw(ioaddr + EL1_RXPTR));
|
||||
lp->txing = 0;
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
else if (txsr & TX_16COLLISIONS)
|
||||
{
|
||||
} else if (txsr & TX_16COLLISIONS) {
|
||||
/*
|
||||
* Timed out
|
||||
*/
|
||||
if (el_debug)
|
||||
printk (KERN_DEBUG "%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name);
|
||||
printk(KERN_DEBUG "%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name);
|
||||
outb(AX_SYS, AX_CMD);
|
||||
lp->txing = 0;
|
||||
dev->stats.tx_aborted_errors++;
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
else if (txsr & TX_COLLISION)
|
||||
{
|
||||
} else if (txsr & TX_COLLISION) {
|
||||
/*
|
||||
* Retrigger xmit.
|
||||
*/
|
||||
|
@ -599,7 +595,8 @@ static irqreturn_t el_interrupt(int irq, void *dev_id)
|
|||
if (el_debug > 6)
|
||||
printk(KERN_DEBUG " retransmitting after a collision.\n");
|
||||
/*
|
||||
* Poor little chip can't reset its own start pointer
|
||||
* Poor little chip can't reset its own start
|
||||
* pointer
|
||||
*/
|
||||
|
||||
outb(AX_SYS, AX_CMD);
|
||||
|
@ -608,53 +605,45 @@ static irqreturn_t el_interrupt(int irq, void *dev_id)
|
|||
dev->stats.collisions++;
|
||||
spin_unlock(&lp->lock);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/*
|
||||
* It worked.. we will now fall through and receive
|
||||
*/
|
||||
dev->stats.tx_packets++;
|
||||
if (el_debug > 6)
|
||||
printk(KERN_DEBUG " Tx succeeded %s\n",
|
||||
(txsr & TX_RDY) ? "." : "but tx is busy!");
|
||||
(txsr & TX_RDY) ? "." : "but tx is busy!");
|
||||
/*
|
||||
* This is safe the interrupt is atomic WRT itself.
|
||||
*/
|
||||
|
||||
lp->txing = 0;
|
||||
netif_wake_queue(dev); /* In case more to transmit */
|
||||
/* In case more to transmit */
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In receive mode.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* In receive mode.
|
||||
*/
|
||||
|
||||
int rxsr = inb(RX_STATUS);
|
||||
if (el_debug > 5)
|
||||
printk(KERN_DEBUG " rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW));
|
||||
printk(KERN_DEBUG " rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS), inw(RX_LOW));
|
||||
/*
|
||||
* Just reading rx_status fixes most errors.
|
||||
*/
|
||||
if (rxsr & RX_MISSED)
|
||||
dev->stats.rx_missed_errors++;
|
||||
else if (rxsr & RX_RUNT)
|
||||
{ /* Handled to avoid board lock-up. */
|
||||
else if (rxsr & RX_RUNT) {
|
||||
/* Handled to avoid board lock-up. */
|
||||
dev->stats.rx_length_errors++;
|
||||
if (el_debug > 5)
|
||||
printk(KERN_DEBUG " runt.\n");
|
||||
}
|
||||
else if (rxsr & RX_GOOD)
|
||||
{
|
||||
} else if (rxsr & RX_GOOD) {
|
||||
/*
|
||||
* Receive worked.
|
||||
*/
|
||||
el_receive(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/*
|
||||
* Nothing? Something is broken!
|
||||
*/
|
||||
|
@ -702,8 +691,7 @@ static void el_receive(struct net_device *dev)
|
|||
if (el_debug > 4)
|
||||
printk(KERN_DEBUG " el_receive %d.\n", pkt_len);
|
||||
|
||||
if ((pkt_len < 60) || (pkt_len > 1536))
|
||||
{
|
||||
if (pkt_len < 60 || pkt_len > 1536) {
|
||||
if (el_debug)
|
||||
printk(KERN_DEBUG "%s: bogus packet, length=%d\n", dev->name, pkt_len);
|
||||
dev->stats.rx_over_errors++;
|
||||
|
@ -722,26 +710,23 @@ static void el_receive(struct net_device *dev)
|
|||
*/
|
||||
|
||||
outw(0x00, GP_LOW);
|
||||
if (skb == NULL)
|
||||
{
|
||||
if (skb == NULL) {
|
||||
printk(KERN_INFO "%s: Memory squeeze, dropping packet.\n", dev->name);
|
||||
dev->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
skb_reserve(skb,2); /* Force 16 byte alignment */
|
||||
} else {
|
||||
skb_reserve(skb, 2); /* Force 16 byte alignment */
|
||||
/*
|
||||
* The read increments through the bytes. The interrupt
|
||||
* handler will fix the pointer when it returns to
|
||||
* receive mode.
|
||||
*/
|
||||
insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);
|
||||
skb->protocol=eth_type_trans(skb,dev);
|
||||
insb(DATAPORT, skb_put(skb, pkt_len), pkt_len);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
netif_rx(skb);
|
||||
dev->last_rx = jiffies;
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes+=pkt_len;
|
||||
dev->stats.rx_bytes += pkt_len;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -760,7 +745,7 @@ static void el_reset(struct net_device *dev)
|
|||
struct net_local *lp = netdev_priv(dev);
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
if (el_debug> 2)
|
||||
if (el_debug > 2)
|
||||
printk(KERN_INFO "3c501 reset...");
|
||||
outb(AX_RESET, AX_CMD); /* Reset the chip */
|
||||
outb(AX_LOOP, AX_CMD); /* Aux control, irq and loopback enabled */
|
||||
|
@ -794,7 +779,8 @@ static int el1_close(struct net_device *dev)
|
|||
int ioaddr = dev->base_addr;
|
||||
|
||||
if (el_debug > 2)
|
||||
printk(KERN_INFO "%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr);
|
||||
printk(KERN_INFO "%s: Shutting down Ethernet card at %#x.\n",
|
||||
dev->name, ioaddr);
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
|
@ -822,18 +808,14 @@ static void set_multicast_list(struct net_device *dev)
|
|||
{
|
||||
int ioaddr = dev->base_addr;
|
||||
|
||||
if(dev->flags&IFF_PROMISC)
|
||||
{
|
||||
if (dev->flags & IFF_PROMISC) {
|
||||
outb(RX_PROM, RX_CMD);
|
||||
inb(RX_STATUS);
|
||||
}
|
||||
else if (dev->mc_list || dev->flags&IFF_ALLMULTI)
|
||||
{
|
||||
outb(RX_MULT, RX_CMD); /* Multicast or all multicast is the same */
|
||||
} else if (dev->mc_list || dev->flags & IFF_ALLMULTI) {
|
||||
/* Multicast or all multicast is the same */
|
||||
outb(RX_MULT, RX_CMD);
|
||||
inb(RX_STATUS); /* Clear status. */
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
outb(RX_NORM, RX_CMD);
|
||||
inb(RX_STATUS);
|
||||
}
|
||||
|
|
|
@ -747,7 +747,7 @@ static void init_82586_mem(struct net_device *dev)
|
|||
int boguscnt = 50;
|
||||
while (readw(shmem+iSCB_STATUS) == 0)
|
||||
if (--boguscnt == 0) {
|
||||
printk("%s: i82586 initialization timed out with status %04x,"
|
||||
printk("%s: i82586 initialization timed out with status %04x, "
|
||||
"cmd %04x.\n", dev->name,
|
||||
readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD));
|
||||
break;
|
||||
|
@ -832,10 +832,11 @@ static void el16_rx(struct net_device *dev)
|
|||
|
||||
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
|
||||
|| (pkt_len & 0xC000) != 0xC000) {
|
||||
printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
|
||||
"next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
|
||||
frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
|
||||
pkt_len);
|
||||
printk(KERN_ERR "%s: Rx frame at %#x corrupted, "
|
||||
"status %04x cmd %04x next %04x "
|
||||
"data-buf @%04x %04x.\n",
|
||||
dev->name, rx_head, frame_status, rfd_cmd,
|
||||
next_rx_frame, data_buffer_addr, pkt_len);
|
||||
} else if ((frame_status & 0x2000) == 0) {
|
||||
/* Frame Rxed, but with error. */
|
||||
dev->stats.rx_errors++;
|
||||
|
@ -851,7 +852,9 @@ static void el16_rx(struct net_device *dev)
|
|||
pkt_len &= 0x3fff;
|
||||
skb = dev_alloc_skb(pkt_len+2);
|
||||
if (skb == NULL) {
|
||||
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
|
||||
printk(KERN_ERR "%s: Memory squeeze, "
|
||||
"dropping packet.\n",
|
||||
dev->name);
|
||||
dev->stats.rx_dropped++;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1361,7 +1361,7 @@ static int boomerang_rx(struct net_device *dev)
|
|||
/* Check if the packet is long enough to just accept without
|
||||
copying to a properly sized skbuff. */
|
||||
if (pkt_len < rx_copybreak
|
||||
&& (skb = dev_alloc_skb(pkt_len + 4)) != 0) {
|
||||
&& (skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
|
||||
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
||||
/* 'skb_put()' points to the start of sk_buff data area. */
|
||||
memcpy(skb_put(skb, pkt_len),
|
||||
|
|
|
@ -277,8 +277,6 @@ static int lance_rx (struct net_device *dev)
|
|||
volatile struct lance_init_block *ib = lp->init_block;
|
||||
volatile struct lance_rx_desc *rd;
|
||||
unsigned char bits;
|
||||
int len = 0; /* XXX shut up gcc warnings */
|
||||
struct sk_buff *skb = 0; /* XXX shut up gcc warnings */
|
||||
#ifdef TEST_HITS
|
||||
int i;
|
||||
#endif
|
||||
|
@ -318,10 +316,10 @@ static int lance_rx (struct net_device *dev)
|
|||
if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
|
||||
if (bits & LE_R1_EOP) dev->stats.rx_errors++;
|
||||
} else {
|
||||
len = (rd->mblength & 0xfff) - 4;
|
||||
skb = dev_alloc_skb (len+2);
|
||||
int len = (rd->mblength & 0xfff) - 4;
|
||||
struct sk_buff *skb = dev_alloc_skb (len+2);
|
||||
|
||||
if (skb == 0) {
|
||||
if (!skb) {
|
||||
printk ("%s: Memory squeeze, deferring packet.\n",
|
||||
dev->name);
|
||||
dev->stats.rx_dropped++;
|
||||
|
|
|
@ -912,6 +912,24 @@ config DM9000
|
|||
To compile this driver as a module, choose M here. The module
|
||||
will be called dm9000.
|
||||
|
||||
config ENC28J60
|
||||
tristate "ENC28J60 support"
|
||||
depends on EXPERIMENTAL && SPI && NET_ETHERNET
|
||||
select CRC32
|
||||
---help---
|
||||
Support for the Microchip EN28J60 ethernet chip.
|
||||
|
||||
To compile this driver as a module, choose M here and read
|
||||
<file:Documentation/networking/net-modules.txt>. The module will be
|
||||
called enc28j60.
|
||||
|
||||
config ENC28J60_WRITEVERIFY
|
||||
bool "Enable write verify"
|
||||
depends on ENC28J60
|
||||
---help---
|
||||
Enable the verify after the buffer write useful for debugging purpose.
|
||||
If unsure, say N.
|
||||
|
||||
config SMC911X
|
||||
tristate "SMSC LAN911[5678] support"
|
||||
select CRC32
|
||||
|
@ -1584,6 +1602,18 @@ config 8139_OLD_RX_RESET
|
|||
experience problems, you can enable this option to restore the
|
||||
old RX-reset behavior. If unsure, say N.
|
||||
|
||||
config R6040
|
||||
tristate "RDC R6040 Fast Ethernet Adapter support (EXPERIMENTAL)"
|
||||
depends on NET_PCI && PCI
|
||||
select CRC32
|
||||
select MII
|
||||
help
|
||||
This is a driver for the R6040 Fast Ethernet MACs found in the
|
||||
the RDC R-321x System-on-chips.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called r6040. This is recommended.
|
||||
|
||||
config SIS900
|
||||
tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
|
||||
depends on NET_PCI && PCI
|
||||
|
@ -1785,7 +1815,7 @@ config DE620
|
|||
|
||||
config SGISEEQ
|
||||
tristate "SGI Seeq ethernet controller support"
|
||||
depends on SGI_IP22
|
||||
depends on SGI_HAS_SEEQ
|
||||
help
|
||||
Say Y here if you have an Seeq based Ethernet network card. This is
|
||||
used in many Silicon Graphics machines.
|
||||
|
@ -1989,6 +2019,28 @@ config IP1000
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called ipg. This is recommended.
|
||||
|
||||
config IGB
|
||||
tristate "Intel(R) 82575 PCI-Express Gigabit Ethernet support"
|
||||
depends on PCI
|
||||
---help---
|
||||
This driver supports Intel(R) 82575 gigabit ethernet family of
|
||||
adapters. 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 general information and support, go to the Intel support
|
||||
website at:
|
||||
|
||||
<http://support.intel.com>
|
||||
|
||||
More specific information on configuring the driver is in
|
||||
<file:Documentation/networking/e1000.txt>.
|
||||
|
||||
To compile this driver as a module, choose M here and read
|
||||
<file:Documentation/networking/net-modules.txt>. The module
|
||||
will be called igb.
|
||||
|
||||
source "drivers/net/ixp2000/Kconfig"
|
||||
|
||||
config MYRI_SBUS
|
||||
|
@ -2560,6 +2612,7 @@ config PASEMI_MAC
|
|||
tristate "PA Semi 1/10Gbit MAC"
|
||||
depends on PPC64 && PCI
|
||||
select PHYLIB
|
||||
select INET_LRO
|
||||
help
|
||||
This driver supports the on-chip 1/10Gbit Ethernet controller on
|
||||
PA Semi's PWRficient line of chips.
|
||||
|
@ -2585,6 +2638,16 @@ config TEHUTI
|
|||
help
|
||||
Tehuti Networks 10G Ethernet NIC
|
||||
|
||||
config BNX2X
|
||||
tristate "Broadcom NetXtremeII 10Gb support"
|
||||
depends on PCI
|
||||
select ZLIB_INFLATE
|
||||
help
|
||||
This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called bnx2x. This is recommended.
|
||||
|
||||
|
||||
endif # NETDEV_10000
|
||||
|
||||
source "drivers/net/tokenring/Kconfig"
|
||||
|
@ -3015,23 +3078,6 @@ config NET_FC
|
|||
adaptor below. You also should have said Y to "SCSI support" and
|
||||
"SCSI generic support".
|
||||
|
||||
config SHAPER
|
||||
tristate "Traffic Shaper (OBSOLETE)"
|
||||
depends on EXPERIMENTAL
|
||||
---help---
|
||||
The traffic shaper is a virtual network device that allows you to
|
||||
limit the rate of outgoing data flow over some other network device.
|
||||
The traffic that you want to slow down can then be routed through
|
||||
these virtual devices. See
|
||||
<file:Documentation/networking/shaper.txt> for more information.
|
||||
|
||||
An alternative to this traffic shaper are traffic schedulers which
|
||||
you'll get if you say Y to "QoS and/or fair queuing" in
|
||||
"Networking options".
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called shaper. If unsure, say N.
|
||||
|
||||
config NETCONSOLE
|
||||
tristate "Network console logging support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
|
|
|
@ -6,12 +6,14 @@ obj-$(CONFIG_E1000) += e1000/
|
|||
obj-$(CONFIG_E1000E) += e1000e/
|
||||
obj-$(CONFIG_IBM_EMAC) += ibm_emac/
|
||||
obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
|
||||
obj-$(CONFIG_IGB) += igb/
|
||||
obj-$(CONFIG_IXGBE) += ixgbe/
|
||||
obj-$(CONFIG_IXGB) += ixgb/
|
||||
obj-$(CONFIG_IP1000) += ipg.o
|
||||
obj-$(CONFIG_CHELSIO_T1) += chelsio/
|
||||
obj-$(CONFIG_CHELSIO_T3) += cxgb3/
|
||||
obj-$(CONFIG_EHEA) += ehea/
|
||||
obj-$(CONFIG_CAN) += can/
|
||||
obj-$(CONFIG_BONDING) += bonding/
|
||||
obj-$(CONFIG_ATL1) += atl1/
|
||||
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
|
||||
|
@ -54,6 +56,7 @@ obj-$(CONFIG_TLAN) += tlan.o
|
|||
obj-$(CONFIG_EPIC100) += epic100.o
|
||||
obj-$(CONFIG_SIS190) += sis190.o
|
||||
obj-$(CONFIG_SIS900) += sis900.o
|
||||
obj-$(CONFIG_R6040) += r6040.o
|
||||
obj-$(CONFIG_YELLOWFIN) += yellowfin.o
|
||||
obj-$(CONFIG_ACENIC) += acenic.o
|
||||
obj-$(CONFIG_ISERIES_VETH) += iseries_veth.o
|
||||
|
@ -63,6 +66,7 @@ obj-$(CONFIG_STNIC) += stnic.o 8390.o
|
|||
obj-$(CONFIG_FEALNX) += fealnx.o
|
||||
obj-$(CONFIG_TIGON3) += tg3.o
|
||||
obj-$(CONFIG_BNX2) += bnx2.o
|
||||
obj-$(CONFIG_BNX2X) += bnx2x.o
|
||||
spidernet-y += spider_net.o spider_net_ethtool.o
|
||||
obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
|
||||
obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
|
||||
|
@ -92,7 +96,6 @@ obj-$(CONFIG_NET_SB1000) += sb1000.o
|
|||
obj-$(CONFIG_MAC8390) += mac8390.o
|
||||
obj-$(CONFIG_APNE) += apne.o 8390.o
|
||||
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
|
||||
obj-$(CONFIG_SHAPER) += shaper.o
|
||||
obj-$(CONFIG_HP100) += hp100.o
|
||||
obj-$(CONFIG_SMC9194) += smc9194.o
|
||||
obj-$(CONFIG_FEC) += fec.o
|
||||
|
@ -216,6 +219,7 @@ obj-$(CONFIG_DM9000) += dm9000.o
|
|||
obj-$(CONFIG_FEC_8XX) += fec_8xx/
|
||||
obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
|
||||
obj-$(CONFIG_MLX4_CORE) += mlx4/
|
||||
obj-$(CONFIG_ENC28J60) += enc28j60.o
|
||||
|
||||
obj-$(CONFIG_MACB) += macb.o
|
||||
|
||||
|
|
|
@ -269,8 +269,6 @@ static int lance_rx (struct net_device *dev)
|
|||
volatile struct lance_regs *ll = lp->ll;
|
||||
volatile struct lance_rx_desc *rd;
|
||||
unsigned char bits;
|
||||
int len = 0; /* XXX shut up gcc warnings */
|
||||
struct sk_buff *skb = 0; /* XXX shut up gcc warnings */
|
||||
|
||||
#ifdef TEST_HITS
|
||||
int i;
|
||||
|
@ -306,10 +304,10 @@ static int lance_rx (struct net_device *dev)
|
|||
if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
|
||||
if (bits & LE_R1_EOP) dev->stats.rx_errors++;
|
||||
} else {
|
||||
len = (rd->mblength & 0xfff) - 4;
|
||||
skb = dev_alloc_skb (len+2);
|
||||
int len = (rd->mblength & 0xfff) - 4;
|
||||
struct sk_buff *skb = dev_alloc_skb (len+2);
|
||||
|
||||
if (skb == 0) {
|
||||
if (!skb) {
|
||||
printk(KERN_WARNING "%s: Memory squeeze, "
|
||||
"deferring packet.\n", dev->name);
|
||||
dev->stats.rx_dropped++;
|
||||
|
@ -477,7 +475,7 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
struct net_device *last_dev = 0;
|
||||
struct net_device *last_dev;
|
||||
|
||||
static int lance_open (struct net_device *dev)
|
||||
{
|
||||
|
|
|
@ -1945,13 +1945,13 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
|
|||
|
||||
err = pci_enable_device(pdev);
|
||||
if(err){
|
||||
printk(KERN_ERR "amd8111e: Cannot enable new PCI device,"
|
||||
printk(KERN_ERR "amd8111e: Cannot enable new PCI device, "
|
||||
"exiting.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)){
|
||||
printk(KERN_ERR "amd8111e: Cannot find PCI base address"
|
||||
printk(KERN_ERR "amd8111e: Cannot find PCI base address, "
|
||||
"exiting.\n");
|
||||
err = -ENODEV;
|
||||
goto err_disable_pdev;
|
||||
|
|
|
@ -465,8 +465,9 @@ found:
|
|||
/* Snarf the interrupt vector now. */
|
||||
ret = request_irq(irq, &net_interrupt, 0, DRV_NAME, dev);
|
||||
if (ret) {
|
||||
printk (" AT1700 at %#3x is unusable due to a conflict on"
|
||||
"IRQ %d.\n", ioaddr, irq);
|
||||
printk(KERN_ERR "AT1700 at %#3x is unusable due to a "
|
||||
"conflict on IRQ %d.\n",
|
||||
ioaddr, irq);
|
||||
goto err_mca;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,8 @@ static void b44_init_rings(struct b44 *);
|
|||
#define B44_FULL_RESET 1
|
||||
#define B44_FULL_RESET_SKIP_PHY 2
|
||||
#define B44_PARTIAL_RESET 3
|
||||
#define B44_CHIP_RESET_FULL 4
|
||||
#define B44_CHIP_RESET_PARTIAL 5
|
||||
|
||||
static void b44_init_hw(struct b44 *, int);
|
||||
|
||||
|
@ -1259,7 +1261,7 @@ static void b44_clear_stats(struct b44 *bp)
|
|||
}
|
||||
|
||||
/* bp->lock is held. */
|
||||
static void b44_chip_reset(struct b44 *bp)
|
||||
static void b44_chip_reset(struct b44 *bp, int reset_kind)
|
||||
{
|
||||
struct ssb_device *sdev = bp->sdev;
|
||||
|
||||
|
@ -1281,6 +1283,13 @@ static void b44_chip_reset(struct b44 *bp)
|
|||
ssb_device_enable(bp->sdev, 0);
|
||||
b44_clear_stats(bp);
|
||||
|
||||
/*
|
||||
* Don't enable PHY if we are doing a partial reset
|
||||
* we are probably going to power down
|
||||
*/
|
||||
if (reset_kind == B44_CHIP_RESET_PARTIAL)
|
||||
return;
|
||||
|
||||
switch (sdev->bus->bustype) {
|
||||
case SSB_BUSTYPE_SSB:
|
||||
bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
|
||||
|
@ -1316,7 +1325,14 @@ static void b44_chip_reset(struct b44 *bp)
|
|||
static void b44_halt(struct b44 *bp)
|
||||
{
|
||||
b44_disable_ints(bp);
|
||||
b44_chip_reset(bp);
|
||||
/* reset PHY */
|
||||
b44_phy_reset(bp);
|
||||
/* power down PHY */
|
||||
printk(KERN_INFO PFX "%s: powering down PHY\n", bp->dev->name);
|
||||
bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
|
||||
/* now reset the chip, but without enabling the MAC&PHY
|
||||
* part of it. This has to be done _after_ we shut down the PHY */
|
||||
b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
|
||||
}
|
||||
|
||||
/* bp->lock is held. */
|
||||
|
@ -1365,7 +1381,7 @@ static void b44_init_hw(struct b44 *bp, int reset_kind)
|
|||
{
|
||||
u32 val;
|
||||
|
||||
b44_chip_reset(bp);
|
||||
b44_chip_reset(bp, B44_CHIP_RESET_FULL);
|
||||
if (reset_kind == B44_FULL_RESET) {
|
||||
b44_phy_reset(bp);
|
||||
b44_setup_phy(bp);
|
||||
|
@ -1422,7 +1438,7 @@ static int b44_open(struct net_device *dev)
|
|||
err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
|
||||
if (unlikely(err < 0)) {
|
||||
napi_disable(&bp->napi);
|
||||
b44_chip_reset(bp);
|
||||
b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
|
||||
b44_free_rings(bp);
|
||||
b44_free_consistent(bp);
|
||||
goto out;
|
||||
|
@ -2060,11 +2076,11 @@ static int __devinit b44_get_invariants(struct b44 *bp)
|
|||
|
||||
if (sdev->bus->bustype == SSB_BUSTYPE_SSB &&
|
||||
instance > 1) {
|
||||
addr = sdev->bus->sprom.r1.et1mac;
|
||||
bp->phy_addr = sdev->bus->sprom.r1.et1phyaddr;
|
||||
addr = sdev->bus->sprom.et1mac;
|
||||
bp->phy_addr = sdev->bus->sprom.et1phyaddr;
|
||||
} else {
|
||||
addr = sdev->bus->sprom.r1.et0mac;
|
||||
bp->phy_addr = sdev->bus->sprom.r1.et0phyaddr;
|
||||
addr = sdev->bus->sprom.et0mac;
|
||||
bp->phy_addr = sdev->bus->sprom.et0phyaddr;
|
||||
}
|
||||
memcpy(bp->dev->dev_addr, addr, 6);
|
||||
|
||||
|
@ -2188,7 +2204,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
|
|||
/* Chip reset provides power to the b44 MAC & PCI cores, which
|
||||
* is necessary for MAC register access.
|
||||
*/
|
||||
b44_chip_reset(bp);
|
||||
b44_chip_reset(bp, B44_CHIP_RESET_FULL);
|
||||
|
||||
printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n",
|
||||
dev->name, print_mac(mac, dev->dev_addr));
|
||||
|
@ -2212,6 +2228,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev)
|
|||
unregister_netdev(dev);
|
||||
ssb_bus_may_powerdown(sdev->bus);
|
||||
free_netdev(dev);
|
||||
ssb_pcihost_set_power_state(sdev, PCI_D3hot);
|
||||
ssb_set_drvdata(sdev, NULL);
|
||||
}
|
||||
|
||||
|
@ -2240,6 +2257,7 @@ static int b44_suspend(struct ssb_device *sdev, pm_message_t state)
|
|||
b44_setup_wol(bp);
|
||||
}
|
||||
|
||||
ssb_pcihost_set_power_state(sdev, PCI_D3hot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
1337
drivers/net/bnx2.c
1337
drivers/net/bnx2.c
File diff suppressed because it is too large
Load diff
|
@ -154,6 +154,33 @@ struct status_block {
|
|||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* status_block definition
|
||||
*/
|
||||
struct status_block_msix {
|
||||
#if defined(__BIG_ENDIAN)
|
||||
u16 status_tx_quick_consumer_index;
|
||||
u16 status_rx_quick_consumer_index;
|
||||
u16 status_completion_producer_index;
|
||||
u16 status_cmd_consumer_index;
|
||||
u32 status_unused;
|
||||
u16 status_idx;
|
||||
u8 status_unused2;
|
||||
u8 status_blk_num;
|
||||
#elif defined(__LITTLE_ENDIAN)
|
||||
u16 status_rx_quick_consumer_index;
|
||||
u16 status_tx_quick_consumer_index;
|
||||
u16 status_cmd_consumer_index;
|
||||
u16 status_completion_producer_index;
|
||||
u32 status_unused;
|
||||
u8 status_blk_num;
|
||||
u8 status_unused2;
|
||||
u16 status_idx;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BNX2_SBLK_MSIX_ALIGN_SIZE 128
|
||||
|
||||
|
||||
/*
|
||||
* statistics_block definition
|
||||
|
@ -259,6 +286,7 @@ struct l2_fhdr {
|
|||
#define L2_FHDR_STATUS_TCP_SEGMENT (1<<14)
|
||||
#define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
|
||||
|
||||
#define L2_FHDR_STATUS_SPLIT (1<<16)
|
||||
#define L2_FHDR_ERRORS_BAD_CRC (1<<17)
|
||||
#define L2_FHDR_ERRORS_PHY_DECODE (1<<18)
|
||||
#define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
|
||||
|
@ -332,6 +360,12 @@ struct l2_fhdr {
|
|||
#define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014
|
||||
#define BNX2_L2CTX_NX_BDIDX 0x00000018
|
||||
|
||||
#define BNX2_L2CTX_HOST_PG_BDIDX 0x00000044
|
||||
#define BNX2_L2CTX_PG_BUF_SIZE 0x00000048
|
||||
#define BNX2_L2CTX_RBDC_KEY 0x0000004c
|
||||
#define BNX2_L2CTX_RBDC_JUMBO_KEY 0x3ffe
|
||||
#define BNX2_L2CTX_NX_PG_BDHADDR_HI 0x00000050
|
||||
#define BNX2_L2CTX_NX_PG_BDHADDR_LO 0x00000054
|
||||
|
||||
/*
|
||||
* pci_config_l definition
|
||||
|
@ -406,6 +440,7 @@ struct l2_fhdr {
|
|||
#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17)
|
||||
#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18)
|
||||
#define BNX2_PCICFG_INT_ACK_CMD_INTERRUPT_NUM (0xfL<<24)
|
||||
#define BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT 24
|
||||
|
||||
#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
|
||||
#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c
|
||||
|
@ -421,6 +456,9 @@ struct l2_fhdr {
|
|||
#define BNX2_PCI_GRC_WINDOW_ADDR_VALUE (0x1ffL<<13)
|
||||
#define BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN (1L<<31)
|
||||
|
||||
#define BNX2_PCI_GRC_WINDOW2_BASE 0xc000
|
||||
#define BNX2_PCI_GRC_WINDOW3_BASE 0xe000
|
||||
|
||||
#define BNX2_PCI_CONFIG_1 0x00000404
|
||||
#define BNX2_PCI_CONFIG_1_RESERVED0 (0xffL<<0)
|
||||
#define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8)
|
||||
|
@ -693,6 +731,8 @@ struct l2_fhdr {
|
|||
#define BNX2_PCI_GRC_WINDOW3_ADDR 0x00000618
|
||||
#define BNX2_PCI_GRC_WINDOW3_ADDR_VALUE (0x1ffL<<13)
|
||||
|
||||
#define BNX2_MSIX_TABLE_ADDR 0x318000
|
||||
#define BNX2_MSIX_PBA_ADDR 0x31c000
|
||||
|
||||
/*
|
||||
* misc_reg definition
|
||||
|
@ -4445,6 +4485,14 @@ struct l2_fhdr {
|
|||
#define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0)
|
||||
#define BNX2_MQ_MEM_RD_DATA2_VALUE_XI (0x7fffffffL<<0)
|
||||
|
||||
#define BNX2_MQ_MAP_L2_3 0x00003d2c
|
||||
#define BNX2_MQ_MAP_L2_3_MQ_OFFSET (0xffL<<0)
|
||||
#define BNX2_MQ_MAP_L2_3_SZ (0x3L<<8)
|
||||
#define BNX2_MQ_MAP_L2_3_CTX_OFFSET (0x2ffL<<10)
|
||||
#define BNX2_MQ_MAP_L2_3_BIN_OFFSET (0x7L<<23)
|
||||
#define BNX2_MQ_MAP_L2_3_ARM (0x3L<<26)
|
||||
#define BNX2_MQ_MAP_L2_3_ENA (0x1L<<31)
|
||||
#define BNX2_MQ_MAP_L2_3_DEFAULT 0x82004646
|
||||
|
||||
/*
|
||||
* tsch_reg definition
|
||||
|
@ -6296,6 +6344,15 @@ struct l2_fhdr {
|
|||
#define MII_BNX2_DSP_RW_PORT 0x15
|
||||
#define MII_BNX2_DSP_ADDRESS 0x17
|
||||
#define MII_BNX2_DSP_EXPAND_REG 0x0f00
|
||||
#define MII_EXPAND_REG1 (MII_BNX2_DSP_EXPAND_REG | 1)
|
||||
#define MII_EXPAND_REG1_RUDI_C 0x20
|
||||
#define MII_EXPAND_SERDES_CTL (MII_BNX2_DSP_EXPAND_REG | 2)
|
||||
|
||||
#define MII_BNX2_MISC_SHADOW 0x1c
|
||||
#define MISC_SHDW_AN_DBG 0x6800
|
||||
#define MISC_SHDW_AN_DBG_NOSYNC 0x0002
|
||||
#define MISC_SHDW_MODE_CTL 0x7c00
|
||||
#define MISC_SHDW_MODE_CTL_SIG_DET 0x0010
|
||||
|
||||
#define MII_BNX2_BLK_ADDR 0x1f
|
||||
#define MII_BNX2_BLK_ADDR_IEEE0 0x0000
|
||||
|
@ -6336,7 +6393,7 @@ struct l2_fhdr {
|
|||
#define MAX_ETHERNET_PACKET_SIZE 1514
|
||||
#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
|
||||
|
||||
#define RX_COPY_THRESH 92
|
||||
#define RX_COPY_THRESH 128
|
||||
|
||||
#define BNX2_MISC_ENABLE_DEFAULT 0x7ffffff
|
||||
|
||||
|
@ -6355,9 +6412,11 @@ struct l2_fhdr {
|
|||
#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
|
||||
|
||||
#define MAX_RX_RINGS 4
|
||||
#define MAX_RX_PG_RINGS 16
|
||||
#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
|
||||
#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
|
||||
#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
|
||||
#define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS)
|
||||
|
||||
#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
|
||||
(MAX_TX_DESC_CNT - 1)) ? \
|
||||
|
@ -6370,6 +6429,7 @@ struct l2_fhdr {
|
|||
(x) + 2 : (x) + 1
|
||||
|
||||
#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
|
||||
#define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
|
||||
|
||||
#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
|
||||
#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
|
||||
|
@ -6408,6 +6468,17 @@ struct sw_bd {
|
|||
DECLARE_PCI_UNMAP_ADDR(mapping)
|
||||
};
|
||||
|
||||
struct sw_pg {
|
||||
struct page *page;
|
||||
DECLARE_PCI_UNMAP_ADDR(mapping)
|
||||
};
|
||||
|
||||
#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
|
||||
#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
|
||||
#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
|
||||
#define SW_TXBD_RING_SIZE (sizeof(struct sw_bd) * TX_DESC_CNT)
|
||||
#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
|
||||
|
||||
/* Buffered flash (Atmel: AT45DB011B) specific information */
|
||||
#define SEEPROM_PAGE_BITS 2
|
||||
#define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS)
|
||||
|
@ -6465,6 +6536,39 @@ struct flash_spec {
|
|||
u8 *name;
|
||||
};
|
||||
|
||||
#define BNX2_MAX_MSIX_HW_VEC 9
|
||||
#define BNX2_MAX_MSIX_VEC 2
|
||||
#define BNX2_BASE_VEC 0
|
||||
#define BNX2_TX_VEC 1
|
||||
#define BNX2_TX_INT_NUM (BNX2_TX_VEC << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT)
|
||||
|
||||
struct bnx2_irq {
|
||||
irq_handler_t handler;
|
||||
u16 vector;
|
||||
u8 requested;
|
||||
char name[16];
|
||||
};
|
||||
|
||||
struct bnx2_napi {
|
||||
struct napi_struct napi ____cacheline_aligned;
|
||||
struct bnx2 *bp;
|
||||
struct status_block *status_blk;
|
||||
struct status_block_msix *status_blk_msix;
|
||||
u32 last_status_idx;
|
||||
u32 int_num;
|
||||
|
||||
u16 tx_cons;
|
||||
u16 hw_tx_cons;
|
||||
|
||||
u32 rx_prod_bseq;
|
||||
u16 rx_prod;
|
||||
u16 rx_cons;
|
||||
|
||||
u16 rx_pg_prod;
|
||||
u16 rx_pg_cons;
|
||||
|
||||
};
|
||||
|
||||
struct bnx2 {
|
||||
/* Fields used in the tx and intr/napi performance paths are grouped */
|
||||
/* together in the beginning of the structure. */
|
||||
|
@ -6473,33 +6577,32 @@ struct bnx2 {
|
|||
struct net_device *dev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
atomic_t intr_sem;
|
||||
|
||||
struct status_block *status_blk;
|
||||
u32 last_status_idx;
|
||||
|
||||
u32 flags;
|
||||
#define PCIX_FLAG 0x00000001
|
||||
#define PCI_32BIT_FLAG 0x00000002
|
||||
#define ONE_TDMA_FLAG 0x00000004 /* no longer used */
|
||||
#define NO_WOL_FLAG 0x00000008
|
||||
#define USING_MSI_FLAG 0x00000020
|
||||
#define ASF_ENABLE_FLAG 0x00000040
|
||||
#define MSI_CAP_FLAG 0x00000080
|
||||
#define ONE_SHOT_MSI_FLAG 0x00000100
|
||||
#define PCIE_FLAG 0x00000200
|
||||
#define BNX2_FLAG_PCIX 0x00000001
|
||||
#define BNX2_FLAG_PCI_32BIT 0x00000002
|
||||
#define BNX2_FLAG_MSIX_CAP 0x00000004
|
||||
#define BNX2_FLAG_NO_WOL 0x00000008
|
||||
#define BNX2_FLAG_USING_MSI 0x00000020
|
||||
#define BNX2_FLAG_ASF_ENABLE 0x00000040
|
||||
#define BNX2_FLAG_MSI_CAP 0x00000080
|
||||
#define BNX2_FLAG_ONE_SHOT_MSI 0x00000100
|
||||
#define BNX2_FLAG_PCIE 0x00000200
|
||||
#define BNX2_FLAG_USING_MSIX 0x00000400
|
||||
#define BNX2_FLAG_USING_MSI_OR_MSIX (BNX2_FLAG_USING_MSI | \
|
||||
BNX2_FLAG_USING_MSIX)
|
||||
#define BNX2_FLAG_JUMBO_BROKEN 0x00000800
|
||||
|
||||
/* Put tx producer and consumer fields in separate cache lines. */
|
||||
|
||||
u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
|
||||
u16 tx_prod;
|
||||
u8 tx_vec;
|
||||
u32 tx_bidx_addr;
|
||||
u32 tx_bseq_addr;
|
||||
|
||||
u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
|
||||
u16 hw_tx_cons;
|
||||
struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC];
|
||||
|
||||
#ifdef BCM_VLAN
|
||||
struct vlan_group *vlgrp;
|
||||
|
@ -6508,16 +6611,17 @@ struct bnx2 {
|
|||
u32 rx_offset;
|
||||
u32 rx_buf_use_size; /* useable size */
|
||||
u32 rx_buf_size; /* with alignment */
|
||||
u32 rx_copy_thresh;
|
||||
u32 rx_jumbo_thresh;
|
||||
u32 rx_max_ring_idx;
|
||||
|
||||
u32 rx_prod_bseq;
|
||||
u16 rx_prod;
|
||||
u16 rx_cons;
|
||||
u32 rx_max_pg_ring_idx;
|
||||
|
||||
u32 rx_csum;
|
||||
|
||||
struct sw_bd *rx_buf_ring;
|
||||
struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
|
||||
struct sw_pg *rx_pg_ring;
|
||||
struct rx_bd *rx_pg_desc_ring[MAX_RX_PG_RINGS];
|
||||
|
||||
/* TX constants */
|
||||
struct tx_bd *tx_desc_ring;
|
||||
|
@ -6540,15 +6644,16 @@ struct bnx2 {
|
|||
spinlock_t indirect_lock;
|
||||
|
||||
u32 phy_flags;
|
||||
#define PHY_SERDES_FLAG 1
|
||||
#define PHY_CRC_FIX_FLAG 2
|
||||
#define PHY_PARALLEL_DETECT_FLAG 4
|
||||
#define PHY_2_5G_CAPABLE_FLAG 8
|
||||
#define PHY_INT_MODE_MASK_FLAG 0x300
|
||||
#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
|
||||
#define PHY_INT_MODE_LINK_READY_FLAG 0x200
|
||||
#define PHY_DIS_EARLY_DAC_FLAG 0x400
|
||||
#define REMOTE_PHY_CAP_FLAG 0x800
|
||||
#define BNX2_PHY_FLAG_SERDES 0x00000001
|
||||
#define BNX2_PHY_FLAG_CRC_FIX 0x00000002
|
||||
#define BNX2_PHY_FLAG_PARALLEL_DETECT 0x00000004
|
||||
#define BNX2_PHY_FLAG_2_5G_CAPABLE 0x00000008
|
||||
#define BNX2_PHY_FLAG_INT_MODE_MASK 0x00000300
|
||||
#define BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING 0x00000100
|
||||
#define BNX2_PHY_FLAG_INT_MODE_LINK_READY 0x00000200
|
||||
#define BNX2_PHY_FLAG_DIS_EARLY_DAC 0x00000400
|
||||
#define BNX2_PHY_FLAG_REMOTE_PHY_CAP 0x00000800
|
||||
#define BNX2_PHY_FLAG_FORCED_DOWN 0x00001000
|
||||
|
||||
u32 mii_bmcr;
|
||||
u32 mii_bmsr;
|
||||
|
@ -6605,6 +6710,10 @@ struct bnx2 {
|
|||
int rx_ring_size;
|
||||
dma_addr_t rx_desc_mapping[MAX_RX_RINGS];
|
||||
|
||||
int rx_max_pg_ring;
|
||||
int rx_pg_ring_size;
|
||||
dma_addr_t rx_pg_desc_mapping[MAX_RX_PG_RINGS];
|
||||
|
||||
u16 tx_quick_cons_trip;
|
||||
u16 tx_quick_cons_trip_int;
|
||||
u16 rx_quick_cons_trip;
|
||||
|
@ -6622,6 +6731,7 @@ struct bnx2 {
|
|||
|
||||
u32 stats_ticks;
|
||||
|
||||
struct status_block *status_blk;
|
||||
dma_addr_t status_blk_mapping;
|
||||
|
||||
struct statistics_block *stats_blk;
|
||||
|
@ -6680,6 +6790,9 @@ struct bnx2 {
|
|||
u32 flash_size;
|
||||
|
||||
int status_stats_size;
|
||||
|
||||
struct bnx2_irq irq_tbl[BNX2_MAX_MSIX_VEC];
|
||||
int irq_nvecs;
|
||||
};
|
||||
|
||||
static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
|
||||
|
@ -6737,7 +6850,7 @@ struct fw_info {
|
|||
const u32 text_addr;
|
||||
const u32 text_len;
|
||||
const u32 text_index;
|
||||
u32 *text;
|
||||
__le32 *text;
|
||||
u8 *gz_text;
|
||||
const u32 gz_text_len;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
9064
drivers/net/bnx2x.c
Normal file
9064
drivers/net/bnx2x.c
Normal file
File diff suppressed because it is too large
Load diff
1071
drivers/net/bnx2x.h
Normal file
1071
drivers/net/bnx2x.h
Normal file
File diff suppressed because it is too large
Load diff
198
drivers/net/bnx2x_fw_defs.h
Normal file
198
drivers/net/bnx2x_fw_defs.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/* bnx2x_fw_defs.h: Broadcom Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#define CSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index)\
|
||||
(0x1922 + (port * 0x40) + (index * 0x4))
|
||||
#define CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)\
|
||||
(0x1900 + (port * 0x40))
|
||||
#define CSTORM_HC_BTR_OFFSET(port)\
|
||||
(0x1984 + (port * 0xc0))
|
||||
#define CSTORM_SB_HC_DISABLE_OFFSET(port, cpu_id, index)\
|
||||
(0x141a + (port * 0x280) + (cpu_id * 0x28) + (index * 0x4))
|
||||
#define CSTORM_SB_HC_TIMEOUT_OFFSET(port, cpu_id, index)\
|
||||
(0x1418 + (port * 0x280) + (cpu_id * 0x28) + (index * 0x4))
|
||||
#define CSTORM_SB_HOST_SB_ADDR_OFFSET(port, cpu_id)\
|
||||
(0x1400 + (port * 0x280) + (cpu_id * 0x28))
|
||||
#define CSTORM_STATS_FLAGS_OFFSET(port) (0x5108 + (port * 0x8))
|
||||
#define TSTORM_CLIENT_CONFIG_OFFSET(port, client_id)\
|
||||
(0x1510 + (port * 0x240) + (client_id * 0x20))
|
||||
#define TSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index)\
|
||||
(0x138a + (port * 0x28) + (index * 0x4))
|
||||
#define TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)\
|
||||
(0x1370 + (port * 0x28))
|
||||
#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(port)\
|
||||
(0x4b70 + (port * 0x8))
|
||||
#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(function)\
|
||||
(0x1418 + (function * 0x30))
|
||||
#define TSTORM_HC_BTR_OFFSET(port)\
|
||||
(0x13c4 + (port * 0x18))
|
||||
#define TSTORM_INDIRECTION_TABLE_OFFSET(port)\
|
||||
(0x22c8 + (port * 0x80))
|
||||
#define TSTORM_INDIRECTION_TABLE_SIZE 0x80
|
||||
#define TSTORM_MAC_FILTER_CONFIG_OFFSET(port)\
|
||||
(0x1420 + (port * 0x30))
|
||||
#define TSTORM_RCQ_PROD_OFFSET(port, client_id)\
|
||||
(0x1508 + (port * 0x240) + (client_id * 0x20))
|
||||
#define TSTORM_STATS_FLAGS_OFFSET(port) (0x4b90 + (port * 0x8))
|
||||
#define USTORM_DEF_SB_HC_DISABLE_OFFSET(port, index)\
|
||||
(0x191a + (port * 0x28) + (index * 0x4))
|
||||
#define USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)\
|
||||
(0x1900 + (port * 0x28))
|
||||
#define USTORM_HC_BTR_OFFSET(port)\
|
||||
(0x1954 + (port * 0xb8))
|
||||
#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(port)\
|
||||
(0x5408 + (port * 0x8))
|
||||
#define USTORM_SB_HC_DISABLE_OFFSET(port, cpu_id, index)\
|
||||
(0x141a + (port * 0x280) + (cpu_id * 0x28) + (index * 0x4))
|
||||
#define USTORM_SB_HC_TIMEOUT_OFFSET(port, cpu_id, index)\
|
||||
(0x1418 + (port * 0x280) + (cpu_id * 0x28) + (index * 0x4))
|
||||
#define USTORM_SB_HOST_SB_ADDR_OFFSET(port, cpu_id)\
|
||||
(0x1400 + (port * 0x280) + (cpu_id * 0x28))
|
||||
#define XSTORM_ASSERT_LIST_INDEX_OFFSET 0x1000
|
||||
#define XSTORM_ASSERT_LIST_OFFSET(idx) (0x1020 + (idx * 0x10))
|
||||
#define XSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index)\
|
||||
(0x141a + (port * 0x28) + (index * 0x4))
|
||||
#define XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port)\
|
||||
(0x1400 + (port * 0x28))
|
||||
#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(port)\
|
||||
(0x5408 + (port * 0x8))
|
||||
#define XSTORM_HC_BTR_OFFSET(port)\
|
||||
(0x1454 + (port * 0x18))
|
||||
#define XSTORM_SPQ_PAGE_BASE_OFFSET(port)\
|
||||
(0x5328 + (port * 0x18))
|
||||
#define XSTORM_SPQ_PROD_OFFSET(port)\
|
||||
(0x5330 + (port * 0x18))
|
||||
#define XSTORM_STATS_FLAGS_OFFSET(port) (0x53f8 + (port * 0x8))
|
||||
#define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
|
||||
|
||||
/**
|
||||
* This file defines HSI constatnts for the ETH flow
|
||||
*/
|
||||
|
||||
/* hash types */
|
||||
#define DEFAULT_HASH_TYPE 0
|
||||
#define IPV4_HASH_TYPE 1
|
||||
#define TCP_IPV4_HASH_TYPE 2
|
||||
#define IPV6_HASH_TYPE 3
|
||||
#define TCP_IPV6_HASH_TYPE 4
|
||||
|
||||
/* values of command IDs in the ramrod message */
|
||||
#define RAMROD_CMD_ID_ETH_PORT_SETUP (80)
|
||||
#define RAMROD_CMD_ID_ETH_CLIENT_SETUP (85)
|
||||
#define RAMROD_CMD_ID_ETH_STAT_QUERY (90)
|
||||
#define RAMROD_CMD_ID_ETH_UPDATE (100)
|
||||
#define RAMROD_CMD_ID_ETH_HALT (105)
|
||||
#define RAMROD_CMD_ID_ETH_SET_MAC (110)
|
||||
#define RAMROD_CMD_ID_ETH_CFC_DEL (115)
|
||||
#define RAMROD_CMD_ID_ETH_PORT_DEL (120)
|
||||
#define RAMROD_CMD_ID_ETH_FORWARD_SETUP (125)
|
||||
|
||||
|
||||
/* command values for set mac command */
|
||||
#define T_ETH_MAC_COMMAND_SET 0
|
||||
#define T_ETH_MAC_COMMAND_INVALIDATE 1
|
||||
|
||||
#define T_ETH_INDIRECTION_TABLE_SIZE 128
|
||||
|
||||
/* Maximal L2 clients supported */
|
||||
#define ETH_MAX_RX_CLIENTS (18)
|
||||
|
||||
/**
|
||||
* This file defines HSI constatnts common to all microcode flows
|
||||
*/
|
||||
|
||||
/* Connection types */
|
||||
#define ETH_CONNECTION_TYPE 0
|
||||
|
||||
#define PROTOCOL_STATE_BIT_OFFSET 6
|
||||
|
||||
#define ETH_STATE (ETH_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
|
||||
|
||||
/* microcode fixed page page size 4K (chains and ring segments) */
|
||||
#define MC_PAGE_SIZE (4096)
|
||||
|
||||
/* Host coalescing constants */
|
||||
|
||||
/* IGU constants */
|
||||
#define IGU_PORT_BASE 0x0400
|
||||
|
||||
#define IGU_ADDR_MSIX 0x0000
|
||||
#define IGU_ADDR_INT_ACK 0x0200
|
||||
#define IGU_ADDR_PROD_UPD 0x0201
|
||||
#define IGU_ADDR_ATTN_BITS_UPD 0x0202
|
||||
#define IGU_ADDR_ATTN_BITS_SET 0x0203
|
||||
#define IGU_ADDR_ATTN_BITS_CLR 0x0204
|
||||
#define IGU_ADDR_COALESCE_NOW 0x0205
|
||||
#define IGU_ADDR_SIMD_MASK 0x0206
|
||||
#define IGU_ADDR_SIMD_NOMASK 0x0207
|
||||
#define IGU_ADDR_MSI_CTL 0x0210
|
||||
#define IGU_ADDR_MSI_ADDR_LO 0x0211
|
||||
#define IGU_ADDR_MSI_ADDR_HI 0x0212
|
||||
#define IGU_ADDR_MSI_DATA 0x0213
|
||||
|
||||
#define IGU_INT_ENABLE 0
|
||||
#define IGU_INT_DISABLE 1
|
||||
#define IGU_INT_NOP 2
|
||||
#define IGU_INT_NOP2 3
|
||||
|
||||
/* index numbers */
|
||||
#define HC_USTORM_DEF_SB_NUM_INDICES 4
|
||||
#define HC_CSTORM_DEF_SB_NUM_INDICES 8
|
||||
#define HC_XSTORM_DEF_SB_NUM_INDICES 4
|
||||
#define HC_TSTORM_DEF_SB_NUM_INDICES 4
|
||||
#define HC_USTORM_SB_NUM_INDICES 4
|
||||
#define HC_CSTORM_SB_NUM_INDICES 4
|
||||
|
||||
/* index values - which counterto update */
|
||||
|
||||
#define HC_INDEX_U_ETH_RX_CQ_CONS 1
|
||||
|
||||
#define HC_INDEX_C_ETH_TX_CQ_CONS 1
|
||||
|
||||
#define HC_INDEX_DEF_X_SPQ_CONS 0
|
||||
|
||||
#define HC_INDEX_DEF_C_ETH_FW_TX_CQ_CONS 2
|
||||
#define HC_INDEX_DEF_C_ETH_SLOW_PATH 3
|
||||
|
||||
/* used by the driver to get the SB offset */
|
||||
#define USTORM_ID 0
|
||||
#define CSTORM_ID 1
|
||||
#define XSTORM_ID 2
|
||||
#define TSTORM_ID 3
|
||||
#define ATTENTION_ID 4
|
||||
|
||||
/* max number of slow path commands per port */
|
||||
#define MAX_RAMRODS_PER_PORT (8)
|
||||
|
||||
/* values for RX ETH CQE type field */
|
||||
#define RX_ETH_CQE_TYPE_ETH_FASTPATH (0)
|
||||
#define RX_ETH_CQE_TYPE_ETH_RAMROD (1)
|
||||
|
||||
/* MAC address list size */
|
||||
#define T_MAC_ADDRESS_LIST_SIZE (96)
|
||||
|
||||
#define XSTORM_IP_ID_ROLL_HALF 0x8000
|
||||
#define XSTORM_IP_ID_ROLL_ALL 0
|
||||
|
||||
#define FW_LOG_LIST_SIZE (50)
|
||||
|
||||
#define NUM_OF_PROTOCOLS 4
|
||||
#define MAX_COS_NUMBER 16
|
||||
#define MAX_T_STAT_COUNTER_ID 18
|
||||
|
||||
#define T_FAIR 1
|
||||
#define FAIR_MEM 2
|
||||
#define RS_PERIODIC_TIMEOUT_IN_SDM_TICS 25
|
||||
|
||||
#define UNKNOWN_ADDRESS 0
|
||||
#define UNICAST_ADDRESS 1
|
||||
#define MULTICAST_ADDRESS 2
|
||||
#define BROADCAST_ADDRESS 3
|
||||
|
2176
drivers/net/bnx2x_hsi.h
Normal file
2176
drivers/net/bnx2x_hsi.h
Normal file
File diff suppressed because it is too large
Load diff
564
drivers/net/bnx2x_init.h
Normal file
564
drivers/net/bnx2x_init.h
Normal file
|
@ -0,0 +1,564 @@
|
|||
/* bnx2x_init.h: Broadcom Everest network driver.
|
||||
*
|
||||
* Copyright (c) 2007 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* Written by: Eliezer Tamir <eliezert@broadcom.com>
|
||||
*/
|
||||
|
||||
#ifndef BNX2X_INIT_H
|
||||
#define BNX2X_INIT_H
|
||||
|
||||
#define COMMON 0x1
|
||||
#define PORT0 0x2
|
||||
#define PORT1 0x4
|
||||
|
||||
#define INIT_EMULATION 0x1
|
||||
#define INIT_FPGA 0x2
|
||||
#define INIT_ASIC 0x4
|
||||
#define INIT_HARDWARE 0x7
|
||||
|
||||
#define STORM_INTMEM_SIZE (0x5800 / 4)
|
||||
#define TSTORM_INTMEM_ADDR 0x1a0000
|
||||
#define CSTORM_INTMEM_ADDR 0x220000
|
||||
#define XSTORM_INTMEM_ADDR 0x2a0000
|
||||
#define USTORM_INTMEM_ADDR 0x320000
|
||||
|
||||
|
||||
/* Init operation types and structures */
|
||||
|
||||
#define OP_RD 0x1 /* read single register */
|
||||
#define OP_WR 0x2 /* write single register */
|
||||
#define OP_IW 0x3 /* write single register using mailbox */
|
||||
#define OP_SW 0x4 /* copy a string to the device */
|
||||
#define OP_SI 0x5 /* copy a string using mailbox */
|
||||
#define OP_ZR 0x6 /* clear memory */
|
||||
#define OP_ZP 0x7 /* unzip then copy with DMAE */
|
||||
#define OP_WB 0x8 /* copy a string using DMAE */
|
||||
|
||||
struct raw_op {
|
||||
u32 op :8;
|
||||
u32 offset :24;
|
||||
u32 raw_data;
|
||||
};
|
||||
|
||||
struct op_read {
|
||||
u32 op :8;
|
||||
u32 offset :24;
|
||||
u32 pad;
|
||||
};
|
||||
|
||||
struct op_write {
|
||||
u32 op :8;
|
||||
u32 offset :24;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct op_string_write {
|
||||
u32 op :8;
|
||||
u32 offset :24;
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u16 data_off;
|
||||
u16 data_len;
|
||||
#else /* __BIG_ENDIAN */
|
||||
u16 data_len;
|
||||
u16 data_off;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct op_zero {
|
||||
u32 op :8;
|
||||
u32 offset :24;
|
||||
u32 len;
|
||||
};
|
||||
|
||||
union init_op {
|
||||
struct op_read read;
|
||||
struct op_write write;
|
||||
struct op_string_write str_wr;
|
||||
struct op_zero zero;
|
||||
struct raw_op raw;
|
||||
};
|
||||
|
||||
#include "bnx2x_init_values.h"
|
||||
|
||||
static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
|
||||
|
||||
static void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr,
|
||||
u32 dst_addr, u32 len32);
|
||||
|
||||
static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len);
|
||||
|
||||
static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
|
||||
u32 len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
REG_WR(bp, addr + i*4, data[i]);
|
||||
if (!(i % 10000)) {
|
||||
touch_softlockup_watchdog();
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INIT_MEM_WR(reg, data, reg_off, len) \
|
||||
bnx2x_init_str_wr(bp, reg + reg_off*4, data, len)
|
||||
|
||||
static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
|
||||
u16 len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
REG_WR_IND(bp, addr + i*4, data[i]);
|
||||
if (!(i % 10000)) {
|
||||
touch_softlockup_watchdog();
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
|
||||
u32 len, int gunzip)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if (gunzip) {
|
||||
int rc;
|
||||
#ifdef __BIG_ENDIAN
|
||||
int i, size;
|
||||
u32 *temp;
|
||||
|
||||
temp = kmalloc(len, GFP_KERNEL);
|
||||
size = (len / 4) + ((len % 4) ? 1 : 0);
|
||||
for (i = 0; i < size; i++)
|
||||
temp[i] = swab32(data[i]);
|
||||
data = temp;
|
||||
#endif
|
||||
rc = bnx2x_gunzip(bp, (u8 *)data, len);
|
||||
if (rc) {
|
||||
DP(NETIF_MSG_HW, "gunzip failed ! rc %d\n", rc);
|
||||
return;
|
||||
}
|
||||
len = bp->gunzip_outlen;
|
||||
#ifdef __BIG_ENDIAN
|
||||
kfree(temp);
|
||||
for (i = 0; i < len; i++)
|
||||
((u32 *)bp->gunzip_buf)[i] =
|
||||
swab32(((u32 *)bp->gunzip_buf)[i]);
|
||||
#endif
|
||||
} else {
|
||||
if ((len * 4) > FW_BUF_SIZE) {
|
||||
BNX2X_ERR("LARGE DMAE OPERATION ! len 0x%x\n", len*4);
|
||||
return;
|
||||
}
|
||||
memcpy(bp->gunzip_buf, data, len * 4);
|
||||
}
|
||||
|
||||
while (len > DMAE_LEN32_MAX) {
|
||||
bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
|
||||
addr + offset, DMAE_LEN32_MAX);
|
||||
offset += DMAE_LEN32_MAX * 4;
|
||||
len -= DMAE_LEN32_MAX;
|
||||
}
|
||||
bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, addr + offset, len);
|
||||
}
|
||||
|
||||
#define INIT_MEM_WB(reg, data, reg_off, len) \
|
||||
bnx2x_init_wr_wb(bp, reg + reg_off*4, data, len, 0)
|
||||
|
||||
#define INIT_GUNZIP_DMAE(reg, data, reg_off, len) \
|
||||
bnx2x_init_wr_wb(bp, reg + reg_off*4, data, len, 1)
|
||||
|
||||
static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if ((len * 4) > FW_BUF_SIZE) {
|
||||
BNX2X_ERR("LARGE DMAE OPERATION ! len 0x%x\n", len * 4);
|
||||
return;
|
||||
}
|
||||
memset(bp->gunzip_buf, fill, len * 4);
|
||||
|
||||
while (len > DMAE_LEN32_MAX) {
|
||||
bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
|
||||
addr + offset, DMAE_LEN32_MAX);
|
||||
offset += DMAE_LEN32_MAX * 4;
|
||||
len -= DMAE_LEN32_MAX;
|
||||
}
|
||||
bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, addr + offset, len);
|
||||
}
|
||||
|
||||
static void bnx2x_init_block(struct bnx2x *bp, u32 op_start, u32 op_end)
|
||||
{
|
||||
int i;
|
||||
union init_op *op;
|
||||
u32 op_type, addr, len;
|
||||
const u32 *data;
|
||||
|
||||
for (i = op_start; i < op_end; i++) {
|
||||
|
||||
op = (union init_op *)&(init_ops[i]);
|
||||
|
||||
op_type = op->str_wr.op;
|
||||
addr = op->str_wr.offset;
|
||||
len = op->str_wr.data_len;
|
||||
data = init_data + op->str_wr.data_off;
|
||||
|
||||
switch (op_type) {
|
||||
case OP_RD:
|
||||
REG_RD(bp, addr);
|
||||
break;
|
||||
case OP_WR:
|
||||
REG_WR(bp, addr, op->write.val);
|
||||
break;
|
||||
case OP_SW:
|
||||
bnx2x_init_str_wr(bp, addr, data, len);
|
||||
break;
|
||||
case OP_WB:
|
||||
bnx2x_init_wr_wb(bp, addr, data, len, 0);
|
||||
break;
|
||||
case OP_SI:
|
||||
bnx2x_init_ind_wr(bp, addr, data, len);
|
||||
break;
|
||||
case OP_ZR:
|
||||
bnx2x_init_fill(bp, addr, 0, op->zero.len);
|
||||
break;
|
||||
case OP_ZP:
|
||||
bnx2x_init_wr_wb(bp, addr, data, len, 1);
|
||||
break;
|
||||
default:
|
||||
BNX2X_ERR("BAD init operation!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* PXP
|
||||
****************************************************************************/
|
||||
/*
|
||||
* This code configures the PCI read/write arbiter
|
||||
* which implements a wighted round robin
|
||||
* between the virtual queues in the chip.
|
||||
*
|
||||
* The values were derived for each PCI max payload and max request size.
|
||||
* since max payload and max request size are only known at run time,
|
||||
* this is done as a separate init stage.
|
||||
*/
|
||||
|
||||
#define NUM_WR_Q 13
|
||||
#define NUM_RD_Q 29
|
||||
#define MAX_RD_ORD 3
|
||||
#define MAX_WR_ORD 2
|
||||
|
||||
/* configuration for one arbiter queue */
|
||||
struct arb_line {
|
||||
int l;
|
||||
int add;
|
||||
int ubound;
|
||||
};
|
||||
|
||||
/* derived configuration for each read queue for each max request size */
|
||||
static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = {
|
||||
{{8 , 64 , 25}, {16 , 64 , 25}, {32 , 64 , 25}, {64 , 64 , 41} },
|
||||
{{4 , 8 , 4}, {4 , 8 , 4}, {4 , 8 , 4}, {4 , 8 , 4} },
|
||||
{{4 , 3 , 3}, {4 , 3 , 3}, {4 , 3 , 3}, {4 , 3 , 3} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {16 , 3 , 11}, {16 , 3 , 11} },
|
||||
{{8 , 64 , 25}, {16 , 64 , 25}, {32 , 64 , 25}, {64 , 64 , 41} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {64 , 3 , 41} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {64 , 3 , 41} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {64 , 3 , 41} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {64 , 3 , 41} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 3 , 6}, {16 , 3 , 11}, {32 , 3 , 21}, {32 , 3 , 21} },
|
||||
{{8 , 64 , 25}, {16 , 64 , 41}, {32 , 64 , 81}, {64 , 64 , 120} }
|
||||
};
|
||||
|
||||
/* derived configuration for each write queue for each max request size */
|
||||
static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = {
|
||||
{{4 , 6 , 3}, {4 , 6 , 3}, {4 , 6 , 3} },
|
||||
{{4 , 2 , 3}, {4 , 2 , 3}, {4 , 2 , 3} },
|
||||
{{8 , 2 , 6}, {16 , 2 , 11}, {16 , 2 , 11} },
|
||||
{{8 , 2 , 6}, {16 , 2 , 11}, {32 , 2 , 21} },
|
||||
{{8 , 2 , 6}, {16 , 2 , 11}, {32 , 2 , 21} },
|
||||
{{8 , 2 , 6}, {16 , 2 , 11}, {32 , 2 , 21} },
|
||||
{{8 , 64 , 25}, {16 , 64 , 25}, {32 , 64 , 25} },
|
||||
{{8 , 2 , 6}, {16 , 2 , 11}, {16 , 2 , 11} },
|
||||
{{8 , 2 , 6}, {16 , 2 , 11}, {16 , 2 , 11} },
|
||||
{{8 , 9 , 6}, {16 , 9 , 11}, {32 , 9 , 21} },
|
||||
{{8 , 47 , 19}, {16 , 47 , 19}, {32 , 47 , 21} },
|
||||
{{8 , 9 , 6}, {16 , 9 , 11}, {16 , 9 , 11} },
|
||||
{{8 , 64 , 25}, {16 , 64 , 41}, {32 , 64 , 81} }
|
||||
};
|
||||
|
||||
/* register adresses for read queues */
|
||||
static const struct arb_line read_arb_addr[NUM_RD_Q-1] = {
|
||||
{PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND0},
|
||||
{PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
|
||||
PXP2_REG_PSWRQ_BW_UB1},
|
||||
{PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
|
||||
PXP2_REG_PSWRQ_BW_UB2},
|
||||
{PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
|
||||
PXP2_REG_PSWRQ_BW_UB3},
|
||||
{PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND4},
|
||||
{PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND5},
|
||||
{PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
|
||||
PXP2_REG_PSWRQ_BW_UB6},
|
||||
{PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
|
||||
PXP2_REG_PSWRQ_BW_UB7},
|
||||
{PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
|
||||
PXP2_REG_PSWRQ_BW_UB8},
|
||||
{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
|
||||
PXP2_REG_PSWRQ_BW_UB9},
|
||||
{PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
|
||||
PXP2_REG_PSWRQ_BW_UB10},
|
||||
{PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
|
||||
PXP2_REG_PSWRQ_BW_UB11},
|
||||
{PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND12},
|
||||
{PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND13},
|
||||
{PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND14},
|
||||
{PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND15},
|
||||
{PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND16},
|
||||
{PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND17},
|
||||
{PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND18},
|
||||
{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND19},
|
||||
{PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND20},
|
||||
{PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND22},
|
||||
{PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND23},
|
||||
{PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND24},
|
||||
{PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND25},
|
||||
{PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND26},
|
||||
{PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27,
|
||||
PXP2_REG_RQ_BW_RD_UBOUND27},
|
||||
{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
|
||||
PXP2_REG_PSWRQ_BW_UB28}
|
||||
};
|
||||
|
||||
/* register adresses for wrtie queues */
|
||||
static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
|
||||
{PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
|
||||
PXP2_REG_PSWRQ_BW_UB1},
|
||||
{PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
|
||||
PXP2_REG_PSWRQ_BW_UB2},
|
||||
{PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
|
||||
PXP2_REG_PSWRQ_BW_UB3},
|
||||
{PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
|
||||
PXP2_REG_PSWRQ_BW_UB6},
|
||||
{PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
|
||||
PXP2_REG_PSWRQ_BW_UB7},
|
||||
{PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
|
||||
PXP2_REG_PSWRQ_BW_UB8},
|
||||
{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
|
||||
PXP2_REG_PSWRQ_BW_UB9},
|
||||
{PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
|
||||
PXP2_REG_PSWRQ_BW_UB10},
|
||||
{PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
|
||||
PXP2_REG_PSWRQ_BW_UB11},
|
||||
{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
|
||||
PXP2_REG_PSWRQ_BW_UB28},
|
||||
{PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29,
|
||||
PXP2_REG_RQ_BW_WR_UBOUND29},
|
||||
{PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30,
|
||||
PXP2_REG_RQ_BW_WR_UBOUND30}
|
||||
};
|
||||
|
||||
static void bnx2x_init_pxp(struct bnx2x *bp)
|
||||
{
|
||||
int r_order, w_order;
|
||||
u32 val, i;
|
||||
|
||||
pci_read_config_word(bp->pdev,
|
||||
bp->pcie_cap + PCI_EXP_DEVCTL, (u16 *)&val);
|
||||
DP(NETIF_MSG_HW, "read 0x%x from devctl\n", val);
|
||||
w_order = ((val & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
|
||||
r_order = ((val & PCI_EXP_DEVCTL_READRQ) >> 12);
|
||||
|
||||
if (r_order > MAX_RD_ORD) {
|
||||
DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n",
|
||||
r_order, MAX_RD_ORD);
|
||||
r_order = MAX_RD_ORD;
|
||||
}
|
||||
if (w_order > MAX_WR_ORD) {
|
||||
DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n",
|
||||
w_order, MAX_WR_ORD);
|
||||
w_order = MAX_WR_ORD;
|
||||
}
|
||||
DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order);
|
||||
|
||||
for (i = 0; i < NUM_RD_Q-1; i++) {
|
||||
REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
|
||||
REG_WR(bp, read_arb_addr[i].add,
|
||||
read_arb_data[i][r_order].add);
|
||||
REG_WR(bp, read_arb_addr[i].ubound,
|
||||
read_arb_data[i][r_order].ubound);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_WR_Q-1; i++) {
|
||||
if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
|
||||
(write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
|
||||
|
||||
REG_WR(bp, write_arb_addr[i].l,
|
||||
write_arb_data[i][w_order].l);
|
||||
|
||||
REG_WR(bp, write_arb_addr[i].add,
|
||||
write_arb_data[i][w_order].add);
|
||||
|
||||
REG_WR(bp, write_arb_addr[i].ubound,
|
||||
write_arb_data[i][w_order].ubound);
|
||||
} else {
|
||||
|
||||
val = REG_RD(bp, write_arb_addr[i].l);
|
||||
REG_WR(bp, write_arb_addr[i].l,
|
||||
val | (write_arb_data[i][w_order].l << 10));
|
||||
|
||||
val = REG_RD(bp, write_arb_addr[i].add);
|
||||
REG_WR(bp, write_arb_addr[i].add,
|
||||
val | (write_arb_data[i][w_order].add << 10));
|
||||
|
||||
val = REG_RD(bp, write_arb_addr[i].ubound);
|
||||
REG_WR(bp, write_arb_addr[i].ubound,
|
||||
val | (write_arb_data[i][w_order].ubound << 7));
|
||||
}
|
||||
}
|
||||
|
||||
val = write_arb_data[NUM_WR_Q-1][w_order].add;
|
||||
val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;
|
||||
val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;
|
||||
REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);
|
||||
|
||||
val = read_arb_data[NUM_RD_Q-1][r_order].add;
|
||||
val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;
|
||||
val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;
|
||||
REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
|
||||
|
||||
REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
|
||||
REG_WR(bp, PXP2_REG_RQ_WR_MBS0 + 8, w_order);
|
||||
REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
|
||||
REG_WR(bp, PXP2_REG_RQ_RD_MBS0 + 8, r_order);
|
||||
|
||||
REG_WR(bp, PXP2_REG_WR_DMAE_TH, (128 << w_order)/16);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* CDU
|
||||
****************************************************************************/
|
||||
|
||||
#define CDU_REGION_NUMBER_XCM_AG 2
|
||||
#define CDU_REGION_NUMBER_UCM_AG 4
|
||||
|
||||
/**
|
||||
* String-to-compress [31:8] = CID (all 24 bits)
|
||||
* String-to-compress [7:4] = Region
|
||||
* String-to-compress [3:0] = Type
|
||||
*/
|
||||
#define CDU_VALID_DATA(_cid, _region, _type) \
|
||||
(((_cid) << 8) | (((_region) & 0xf) << 4) | (((_type) & 0xf)))
|
||||
#define CDU_CRC8(_cid, _region, _type) \
|
||||
calc_crc8(CDU_VALID_DATA(_cid, _region, _type), 0xff)
|
||||
#define CDU_RSRVD_VALUE_TYPE_A(_cid, _region, _type) \
|
||||
(0x80 | (CDU_CRC8(_cid, _region, _type) & 0x7f))
|
||||
#define CDU_RSRVD_VALUE_TYPE_B(_crc, _type) \
|
||||
(0x80 | ((_type) & 0xf << 3) | (CDU_CRC8(_cid, _region, _type) & 0x7))
|
||||
#define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val) ((_val) & ~0x80)
|
||||
|
||||
/*****************************************************************************
|
||||
* Description:
|
||||
* Calculates crc 8 on a word value: polynomial 0-1-2-8
|
||||
* Code was translated from Verilog.
|
||||
****************************************************************************/
|
||||
static u8 calc_crc8(u32 data, u8 crc)
|
||||
{
|
||||
u8 D[32];
|
||||
u8 NewCRC[8];
|
||||
u8 C[8];
|
||||
u8 crc_res;
|
||||
u8 i;
|
||||
|
||||
/* split the data into 31 bits */
|
||||
for (i = 0; i < 32; i++) {
|
||||
D[i] = data & 1;
|
||||
data = data >> 1;
|
||||
}
|
||||
|
||||
/* split the crc into 8 bits */
|
||||
for (i = 0; i < 8; i++) {
|
||||
C[i] = crc & 1;
|
||||
crc = crc >> 1;
|
||||
}
|
||||
|
||||
NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
|
||||
D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
|
||||
C[6] ^ C[7];
|
||||
NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
|
||||
D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
|
||||
D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6];
|
||||
NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
|
||||
D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
|
||||
C[0] ^ C[1] ^ C[4] ^ C[5];
|
||||
NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
|
||||
D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
|
||||
C[1] ^ C[2] ^ C[5] ^ C[6];
|
||||
NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
|
||||
D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
|
||||
C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
|
||||
NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
|
||||
D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
|
||||
C[3] ^ C[4] ^ C[7];
|
||||
NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
|
||||
D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
|
||||
C[5];
|
||||
NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
|
||||
D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
|
||||
C[6];
|
||||
|
||||
crc_res = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
crc_res |= (NewCRC[i] << i);
|
||||
|
||||
return crc_res;
|
||||
}
|
||||
|
||||
|
||||
#endif /* BNX2X_INIT_H */
|
||||
|
6368
drivers/net/bnx2x_init_values.h
Normal file
6368
drivers/net/bnx2x_init_values.h
Normal file
File diff suppressed because it is too large
Load diff
4394
drivers/net/bnx2x_reg.h
Normal file
4394
drivers/net/bnx2x_reg.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2517,7 +2517,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
|||
fl.fl4_dst = targets[i];
|
||||
fl.fl4_tos = RTO_ONLINK;
|
||||
|
||||
rv = ip_route_output_key(&rt, &fl);
|
||||
rv = ip_route_output_key(&init_net, &rt, &fl);
|
||||
if (rv) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_WARNING DRV_NAME
|
||||
|
|
25
drivers/net/can/Kconfig
Normal file
25
drivers/net/can/Kconfig
Normal file
|
@ -0,0 +1,25 @@
|
|||
menu "CAN Device Drivers"
|
||||
depends on CAN
|
||||
|
||||
config CAN_VCAN
|
||||
tristate "Virtual Local CAN Interface (vcan)"
|
||||
depends on CAN
|
||||
default N
|
||||
---help---
|
||||
Similar to the network loopback devices, vcan offers a
|
||||
virtual local CAN interface.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called vcan.
|
||||
|
||||
config CAN_DEBUG_DEVICES
|
||||
bool "CAN devices debugging messages"
|
||||
depends on CAN
|
||||
default N
|
||||
---help---
|
||||
Say Y here if you want the CAN device drivers to produce a bunch of
|
||||
debug messages to the system log. Select this if you are having
|
||||
a problem with CAN support and want to see more of what is going
|
||||
on.
|
||||
|
||||
endmenu
|
5
drivers/net/can/Makefile
Normal file
5
drivers/net/can/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for the Linux Controller Area Network drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_CAN_VCAN) += vcan.o
|
169
drivers/net/can/vcan.c
Normal file
169
drivers/net/can/vcan.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* vcan.c - Virtual CAN interface
|
||||
*
|
||||
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Volkswagen nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* Alternatively, provided that this notice is retained in full, this
|
||||
* software may be distributed under the terms of the GNU General
|
||||
* Public License ("GPL") version 2, in which case the provisions of the
|
||||
* GPL apply INSTEAD OF those given above.
|
||||
*
|
||||
* The provided data structures and external interfaces from this code
|
||||
* are not restricted to be used by modules with a GPL compatible license.
|
||||
*
|
||||
* 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 MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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.
|
||||
*
|
||||
* Send feedback to <socketcan-users@lists.berlios.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/can.h>
|
||||
#include <net/rtnetlink.h>
|
||||
|
||||
static __initdata const char banner[] =
|
||||
KERN_INFO "vcan: Virtual CAN interface driver\n";
|
||||
|
||||
MODULE_DESCRIPTION("virtual CAN interface");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
|
||||
|
||||
|
||||
/*
|
||||
* CAN test feature:
|
||||
* Enable the echo on driver level for testing the CAN core echo modes.
|
||||
* See Documentation/networking/can.txt for details.
|
||||
*/
|
||||
|
||||
static int echo; /* echo testing. Default: 0 (Off) */
|
||||
module_param(echo, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
|
||||
|
||||
|
||||
static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len;
|
||||
|
||||
skb->protocol = htons(ETH_P_CAN);
|
||||
skb->pkt_type = PACKET_BROADCAST;
|
||||
skb->dev = dev;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
int loop;
|
||||
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += skb->len;
|
||||
|
||||
/* set flag whether this packet has to be looped back */
|
||||
loop = skb->pkt_type == PACKET_LOOPBACK;
|
||||
|
||||
if (!echo) {
|
||||
/* no echo handling available inside this driver */
|
||||
|
||||
if (loop) {
|
||||
/*
|
||||
* only count the packets here, because the
|
||||
* CAN core already did the echo for us
|
||||
*/
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/* perform standard echo handling for CAN network interfaces */
|
||||
|
||||
if (loop) {
|
||||
struct sock *srcsk = skb->sk;
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* receive with packet counting */
|
||||
skb->sk = srcsk;
|
||||
vcan_rx(skb, dev);
|
||||
} else {
|
||||
/* no looped packets => no counting */
|
||||
kfree_skb(skb);
|
||||
}
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static void vcan_setup(struct net_device *dev)
|
||||
{
|
||||
dev->type = ARPHRD_CAN;
|
||||
dev->mtu = sizeof(struct can_frame);
|
||||
dev->hard_header_len = 0;
|
||||
dev->addr_len = 0;
|
||||
dev->tx_queue_len = 0;
|
||||
dev->flags = IFF_NOARP;
|
||||
|
||||
/* set flags according to driver capabilities */
|
||||
if (echo)
|
||||
dev->flags |= IFF_ECHO;
|
||||
|
||||
dev->hard_start_xmit = vcan_tx;
|
||||
dev->destructor = free_netdev;
|
||||
}
|
||||
|
||||
static struct rtnl_link_ops vcan_link_ops __read_mostly = {
|
||||
.kind = "vcan",
|
||||
.setup = vcan_setup,
|
||||
};
|
||||
|
||||
static __init int vcan_init_module(void)
|
||||
{
|
||||
printk(banner);
|
||||
|
||||
if (echo)
|
||||
printk(KERN_INFO "vcan: enabled echo on driver level.\n");
|
||||
|
||||
return rtnl_link_register(&vcan_link_ops);
|
||||
}
|
||||
|
||||
static __exit void vcan_cleanup_module(void)
|
||||
{
|
||||
rtnl_link_unregister(&vcan_link_ops);
|
||||
}
|
||||
|
||||
module_init(vcan_init_module);
|
||||
module_exit(vcan_cleanup_module);
|
|
@ -4394,7 +4394,7 @@ static struct {
|
|||
{"tx_fifo_errors"},
|
||||
{"tx_packets"}
|
||||
};
|
||||
#define CAS_NUM_STAT_KEYS (sizeof(ethtool_cassini_statnames)/ETH_GSTRING_LEN)
|
||||
#define CAS_NUM_STAT_KEYS ARRAY_SIZE(ethtool_cassini_statnames)
|
||||
|
||||
static struct {
|
||||
const int offsets; /* neg. values for 2nd arg to cas_read_phy */
|
||||
|
@ -5085,7 +5085,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
|
||||
/* give us access to cassini registers */
|
||||
cp->regs = pci_iomap(pdev, 0, casreg_len);
|
||||
if (cp->regs == 0UL) {
|
||||
if (!cp->regs) {
|
||||
dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
|
|
@ -379,7 +379,7 @@ extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config
|
|||
extern const struct board_info *t1_get_board_info(unsigned int board_id);
|
||||
extern const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
|
||||
unsigned short ssid);
|
||||
extern int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data);
|
||||
extern int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data);
|
||||
extern int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
|
||||
struct adapter_params *p);
|
||||
extern int t1_init_hw_modules(adapter_t *adapter);
|
||||
|
|
|
@ -814,7 +814,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
|
|||
|
||||
e->magic = EEPROM_MAGIC(adapter);
|
||||
for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
|
||||
t1_seeprom_read(adapter, i, (u32 *)&buf[i]);
|
||||
t1_seeprom_read(adapter, i, (__le32 *)&buf[i]);
|
||||
memcpy(data, buf + e->offset, e->len);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1042,7 +1042,7 @@ static int __devinit init_one(struct pci_dev *pdev,
|
|||
pci_using_dac = 1;
|
||||
|
||||
if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
|
||||
CH_ERR("%s: unable to obtain 64-bit DMA for"
|
||||
CH_ERR("%s: unable to obtain 64-bit DMA for "
|
||||
"consistent allocations\n", pci_name(pdev));
|
||||
err = -ENODEV;
|
||||
goto out_disable_pdev;
|
||||
|
|
|
@ -297,6 +297,7 @@ struct peespi *t1_espi_create(adapter_t *adapter)
|
|||
return espi;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
|
||||
{
|
||||
struct peespi *espi = adapter->espi;
|
||||
|
@ -309,6 +310,7 @@ void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
|
|||
writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
|
||||
spin_unlock(&espi->lock);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
|
||||
{
|
||||
|
|
|
@ -62,7 +62,6 @@ void t1_espi_intr_disable(struct peespi *);
|
|||
int t1_espi_intr_handler(struct peespi *);
|
||||
const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi);
|
||||
|
||||
void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val);
|
||||
u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait);
|
||||
int t1_espi_get_mon_t204(adapter_t *, u32 *, u8);
|
||||
|
||||
|
|
|
@ -330,6 +330,8 @@ unsigned int t1_sched_update_parms(struct sge *sge, unsigned int port,
|
|||
return max_avail_segs * (p->mtu - 40);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
* t1_sched_max_avail_bytes() tells the scheduler the maximum amount of
|
||||
* data that can be pushed per port.
|
||||
|
@ -357,6 +359,8 @@ void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port,
|
|||
t1_sched_update_parms(sge, port, 0, 0);
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
|
||||
/*
|
||||
* get_clock() implements a ns clock (see ktime_get)
|
||||
|
|
|
@ -88,8 +88,6 @@ void t1_sge_intr_disable(struct sge *);
|
|||
void t1_sge_intr_clear(struct sge *);
|
||||
const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge);
|
||||
void t1_sge_get_port_stats(const struct sge *sge, int port, struct sge_port_stats *);
|
||||
void t1_sched_set_max_avail_bytes(struct sge *, unsigned int);
|
||||
void t1_sched_set_drain_bits_per_us(struct sge *, unsigned int, unsigned int);
|
||||
unsigned int t1_sched_update_parms(struct sge *, unsigned int, unsigned int,
|
||||
unsigned int);
|
||||
|
||||
|
|
|
@ -563,10 +563,11 @@ struct chelsio_vpd_t {
|
|||
* written to the Control register. The hardware device will set the flag to a
|
||||
* one when 4B have been transferred to the Data register.
|
||||
*/
|
||||
int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data)
|
||||
int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data)
|
||||
{
|
||||
int i = EEPROM_MAX_POLL;
|
||||
u16 val;
|
||||
u32 v;
|
||||
|
||||
if (addr >= EEPROMSIZE || (addr & 3))
|
||||
return -EINVAL;
|
||||
|
@ -582,8 +583,8 @@ int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data)
|
|||
adapter->name, addr);
|
||||
return -EIO;
|
||||
}
|
||||
pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, data);
|
||||
*data = le32_to_cpu(*data);
|
||||
pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, &v);
|
||||
*data = cpu_to_le32(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -593,7 +594,7 @@ static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
|
|||
|
||||
for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
|
||||
ret = t1_seeprom_read(adapter, addr,
|
||||
(u32 *)((u8 *)vpd + addr));
|
||||
(__le32 *)((u8 *)vpd + addr));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -661,9 +661,6 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id)
|
|||
int queue;
|
||||
u32 status;
|
||||
|
||||
if (!dev)
|
||||
return IRQ_NONE;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
|
||||
status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR);
|
||||
|
|
|
@ -71,6 +71,7 @@ enum { /* adapter flags */
|
|||
USING_MSI = (1 << 1),
|
||||
USING_MSIX = (1 << 2),
|
||||
QUEUES_BOUND = (1 << 3),
|
||||
TP_PARITY_INIT = (1 << 4),
|
||||
};
|
||||
|
||||
struct fl_pg_chunk {
|
||||
|
|
|
@ -681,8 +681,8 @@ int t3_phy_intr_handler(struct adapter *adapter);
|
|||
void t3_link_changed(struct adapter *adapter, int port_id);
|
||||
int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
|
||||
const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
|
||||
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
|
||||
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
|
||||
int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data);
|
||||
int t3_seeprom_write(struct adapter *adapter, u32 addr, __le32 data);
|
||||
int t3_seeprom_wp(struct adapter *adapter, int enable);
|
||||
int t3_get_tp_version(struct adapter *adapter, u32 *vers);
|
||||
int t3_check_tpsram_version(struct adapter *adapter, int *must_load);
|
||||
|
|
|
@ -76,20 +76,20 @@ enum {
|
|||
|
||||
#define EEPROM_MAGIC 0x38E2F10C
|
||||
|
||||
#define CH_DEVICE(devid, ssid, idx) \
|
||||
{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
|
||||
#define CH_DEVICE(devid, idx) \
|
||||
{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
|
||||
|
||||
static const struct pci_device_id cxgb3_pci_tbl[] = {
|
||||
CH_DEVICE(0x20, 1, 0), /* PE9000 */
|
||||
CH_DEVICE(0x21, 1, 1), /* T302E */
|
||||
CH_DEVICE(0x22, 1, 2), /* T310E */
|
||||
CH_DEVICE(0x23, 1, 3), /* T320X */
|
||||
CH_DEVICE(0x24, 1, 1), /* T302X */
|
||||
CH_DEVICE(0x25, 1, 3), /* T320E */
|
||||
CH_DEVICE(0x26, 1, 2), /* T310X */
|
||||
CH_DEVICE(0x30, 1, 2), /* T3B10 */
|
||||
CH_DEVICE(0x31, 1, 3), /* T3B20 */
|
||||
CH_DEVICE(0x32, 1, 1), /* T3B02 */
|
||||
CH_DEVICE(0x20, 0), /* PE9000 */
|
||||
CH_DEVICE(0x21, 1), /* T302E */
|
||||
CH_DEVICE(0x22, 2), /* T310E */
|
||||
CH_DEVICE(0x23, 3), /* T320X */
|
||||
CH_DEVICE(0x24, 1), /* T302X */
|
||||
CH_DEVICE(0x25, 3), /* T320E */
|
||||
CH_DEVICE(0x26, 2), /* T310X */
|
||||
CH_DEVICE(0x30, 2), /* T3B10 */
|
||||
CH_DEVICE(0x31, 3), /* T3B20 */
|
||||
CH_DEVICE(0x32, 1), /* T3B02 */
|
||||
{0,}
|
||||
};
|
||||
|
||||
|
@ -306,6 +306,77 @@ static int request_msix_data_irqs(struct adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,
|
||||
unsigned long n)
|
||||
{
|
||||
int attempts = 5;
|
||||
|
||||
while (adap->sge.qs[0].rspq.offload_pkts < init_cnt + n) {
|
||||
if (!--attempts)
|
||||
return -ETIMEDOUT;
|
||||
msleep(10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_tp_parity(struct adapter *adap)
|
||||
{
|
||||
int i;
|
||||
struct sk_buff *skb;
|
||||
struct cpl_set_tcb_field *greq;
|
||||
unsigned long cnt = adap->sge.qs[0].rspq.offload_pkts;
|
||||
|
||||
t3_tp_set_offload_mode(adap, 1);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
struct cpl_smt_write_req *req;
|
||||
|
||||
skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
|
||||
req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req));
|
||||
memset(req, 0, sizeof(*req));
|
||||
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
|
||||
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i));
|
||||
req->iff = i;
|
||||
t3_mgmt_tx(adap, skb);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2048; i++) {
|
||||
struct cpl_l2t_write_req *req;
|
||||
|
||||
skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
|
||||
req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req));
|
||||
memset(req, 0, sizeof(*req));
|
||||
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
|
||||
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, i));
|
||||
req->params = htonl(V_L2T_W_IDX(i));
|
||||
t3_mgmt_tx(adap, skb);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2048; i++) {
|
||||
struct cpl_rte_write_req *req;
|
||||
|
||||
skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
|
||||
req = (struct cpl_rte_write_req *)__skb_put(skb, sizeof(*req));
|
||||
memset(req, 0, sizeof(*req));
|
||||
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
|
||||
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RTE_WRITE_REQ, i));
|
||||
req->l2t_idx = htonl(V_L2T_W_IDX(i));
|
||||
t3_mgmt_tx(adap, skb);
|
||||
}
|
||||
|
||||
skb = alloc_skb(sizeof(*greq), GFP_KERNEL | __GFP_NOFAIL);
|
||||
greq = (struct cpl_set_tcb_field *)__skb_put(skb, sizeof(*greq));
|
||||
memset(greq, 0, sizeof(*greq));
|
||||
greq->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
|
||||
OPCODE_TID(greq) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, 0));
|
||||
greq->mask = cpu_to_be64(1);
|
||||
t3_mgmt_tx(adap, skb);
|
||||
|
||||
i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1);
|
||||
t3_tp_set_offload_mode(adap, 0);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_rss - configure RSS
|
||||
* @adap: the adapter
|
||||
|
@ -336,7 +407,7 @@ static void setup_rss(struct adapter *adap)
|
|||
|
||||
t3_config_rss(adap, F_RQFEEDBACKENABLE | F_TNLLKPEN | F_TNLMAPEN |
|
||||
F_TNLPRTEN | F_TNL2TUPEN | F_TNL4TUPEN |
|
||||
V_RRCPLCPUSIZE(6), cpus, rspq_map);
|
||||
V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
|
||||
}
|
||||
|
||||
static void init_napi(struct adapter *adap)
|
||||
|
@ -410,8 +481,7 @@ static int setup_sge_qsets(struct adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t attr_show(struct device *d, struct device_attribute *attr,
|
||||
char *buf,
|
||||
static ssize_t attr_show(struct device *d, char *buf,
|
||||
ssize_t(*format) (struct net_device *, char *))
|
||||
{
|
||||
ssize_t len;
|
||||
|
@ -423,7 +493,7 @@ static ssize_t attr_show(struct device *d, struct device_attribute *attr,
|
|||
return len;
|
||||
}
|
||||
|
||||
static ssize_t attr_store(struct device *d, struct device_attribute *attr,
|
||||
static ssize_t attr_store(struct device *d,
|
||||
const char *buf, size_t len,
|
||||
ssize_t(*set) (struct net_device *, unsigned int),
|
||||
unsigned int min_val, unsigned int max_val)
|
||||
|
@ -457,7 +527,7 @@ static ssize_t format_##name(struct net_device *dev, char *buf) \
|
|||
static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return attr_show(d, attr, buf, format_##name); \
|
||||
return attr_show(d, buf, format_##name); \
|
||||
}
|
||||
|
||||
static ssize_t set_nfilters(struct net_device *dev, unsigned int val)
|
||||
|
@ -480,7 +550,7 @@ static ssize_t set_nfilters(struct net_device *dev, unsigned int val)
|
|||
static ssize_t store_nfilters(struct device *d, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return attr_store(d, attr, buf, len, set_nfilters, 0, ~0);
|
||||
return attr_store(d, buf, len, set_nfilters, 0, ~0);
|
||||
}
|
||||
|
||||
static ssize_t set_nservers(struct net_device *dev, unsigned int val)
|
||||
|
@ -500,7 +570,7 @@ static ssize_t set_nservers(struct net_device *dev, unsigned int val)
|
|||
static ssize_t store_nservers(struct device *d, struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return attr_store(d, attr, buf, len, set_nservers, 0, ~0);
|
||||
return attr_store(d, buf, len, set_nservers, 0, ~0);
|
||||
}
|
||||
|
||||
#define CXGB3_ATTR_R(name, val_expr) \
|
||||
|
@ -524,7 +594,7 @@ static struct attribute *cxgb3_attrs[] = {
|
|||
|
||||
static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs };
|
||||
|
||||
static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr,
|
||||
static ssize_t tm_attr_show(struct device *d,
|
||||
char *buf, int sched)
|
||||
{
|
||||
struct port_info *pi = netdev_priv(to_net_dev(d));
|
||||
|
@ -550,7 +620,7 @@ static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr,
|
|||
return len;
|
||||
}
|
||||
|
||||
static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr,
|
||||
static ssize_t tm_attr_store(struct device *d,
|
||||
const char *buf, size_t len, int sched)
|
||||
{
|
||||
struct port_info *pi = netdev_priv(to_net_dev(d));
|
||||
|
@ -578,12 +648,12 @@ static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr,
|
|||
static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return tm_attr_show(d, attr, buf, sched); \
|
||||
return tm_attr_show(d, buf, sched); \
|
||||
} \
|
||||
static ssize_t store_##name(struct device *d, struct device_attribute *attr, \
|
||||
const char *buf, size_t len) \
|
||||
{ \
|
||||
return tm_attr_store(d, attr, buf, len, sched); \
|
||||
return tm_attr_store(d, buf, len, sched); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
|
||||
|
||||
|
@ -720,7 +790,7 @@ static int upgrade_fw(struct adapter *adap)
|
|||
else
|
||||
dev_err(dev, "failed to upgrade to firmware %d.%d.%d\n",
|
||||
FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -747,7 +817,7 @@ static int update_tpsram(struct adapter *adap)
|
|||
struct device *dev = &adap->pdev->dev;
|
||||
int ret;
|
||||
char rev;
|
||||
|
||||
|
||||
rev = t3rev2char(adap);
|
||||
if (!rev)
|
||||
return 0;
|
||||
|
@ -761,10 +831,10 @@ static int update_tpsram(struct adapter *adap)
|
|||
buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
|
||||
if (ret)
|
||||
goto release_tpsram;
|
||||
goto release_tpsram;
|
||||
|
||||
ret = t3_set_proto_sram(adap, tpsram->data);
|
||||
if (ret == 0)
|
||||
|
@ -780,7 +850,7 @@ static int update_tpsram(struct adapter *adap)
|
|||
|
||||
release_tpsram:
|
||||
release_firmware(tpsram);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -818,6 +888,7 @@ static int cxgb_up(struct adapter *adap)
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
t3_set_reg_field(adap, A_TP_PARA_REG5, 0, F_RXDDPOFFINIT);
|
||||
t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
|
||||
|
||||
err = setup_sge_qsets(adap);
|
||||
|
@ -839,7 +910,8 @@ static int cxgb_up(struct adapter *adap)
|
|||
if (err)
|
||||
goto irq_err;
|
||||
|
||||
if (request_msix_data_irqs(adap)) {
|
||||
err = request_msix_data_irqs(adap);
|
||||
if (err) {
|
||||
free_irq(adap->msix_info[0].vec, adap);
|
||||
goto irq_err;
|
||||
}
|
||||
|
@ -856,6 +928,16 @@ static int cxgb_up(struct adapter *adap)
|
|||
t3_sge_start(adap);
|
||||
t3_intr_enable(adap);
|
||||
|
||||
if (adap->params.rev >= T3_REV_C && !(adap->flags & TP_PARITY_INIT) &&
|
||||
is_offload(adap) && init_tp_parity(adap) == 0)
|
||||
adap->flags |= TP_PARITY_INIT;
|
||||
|
||||
if (adap->flags & TP_PARITY_INIT) {
|
||||
t3_write_reg(adap, A_TP_INT_CAUSE,
|
||||
F_CMCACHEPERR | F_ARPLUTPERR);
|
||||
t3_write_reg(adap, A_TP_INT_ENABLE, 0x7fbfffff);
|
||||
}
|
||||
|
||||
if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX)
|
||||
bind_qsets(adap);
|
||||
adap->flags |= QUEUES_BOUND;
|
||||
|
@ -1560,7 +1642,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
|
|||
|
||||
e->magic = EEPROM_MAGIC;
|
||||
for (i = e->offset & ~3; !err && i < e->offset + e->len; i += 4)
|
||||
err = t3_seeprom_read(adapter, i, (u32 *) & buf[i]);
|
||||
err = t3_seeprom_read(adapter, i, (__le32 *) & buf[i]);
|
||||
|
||||
if (!err)
|
||||
memcpy(data, buf + e->offset, e->len);
|
||||
|
@ -1573,7 +1655,8 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
|||
{
|
||||
struct port_info *pi = netdev_priv(dev);
|
||||
struct adapter *adapter = pi->adapter;
|
||||
u32 aligned_offset, aligned_len, *p;
|
||||
u32 aligned_offset, aligned_len;
|
||||
__le32 *p;
|
||||
u8 *buf;
|
||||
int err;
|
||||
|
||||
|
@ -1587,11 +1670,11 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
|||
buf = kmalloc(aligned_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
err = t3_seeprom_read(adapter, aligned_offset, (u32 *) buf);
|
||||
err = t3_seeprom_read(adapter, aligned_offset, (__le32 *) buf);
|
||||
if (!err && aligned_len > 4)
|
||||
err = t3_seeprom_read(adapter,
|
||||
aligned_offset + aligned_len - 4,
|
||||
(u32 *) & buf[aligned_len - 4]);
|
||||
(__le32 *) & buf[aligned_len - 4]);
|
||||
if (err)
|
||||
goto out;
|
||||
memcpy(buf + (eeprom->offset & 3), data, eeprom->len);
|
||||
|
@ -1602,7 +1685,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
for (p = (u32 *) buf; !err && aligned_len; aligned_len -= 4, p++) {
|
||||
for (p = (__le32 *) buf; !err && aligned_len; aligned_len -= 4, p++) {
|
||||
err = t3_seeprom_write(adapter, aligned_offset, *p);
|
||||
aligned_offset += 4;
|
||||
}
|
||||
|
@ -2144,7 +2227,7 @@ static void cxgb_netpoll(struct net_device *dev)
|
|||
for (qidx = pi->first_qset; qidx < pi->first_qset + pi->nqsets; qidx++) {
|
||||
struct sge_qset *qs = &adapter->sge.qs[qidx];
|
||||
void *source;
|
||||
|
||||
|
||||
if (adapter->flags & USING_MSIX)
|
||||
source = qs;
|
||||
else
|
||||
|
@ -2315,6 +2398,106 @@ void t3_fatal_err(struct adapter *adapter)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_io_error_detected - called when PCI error is detected
|
||||
* @pdev: Pointer to PCI device
|
||||
* @state: The current pci connection state
|
||||
*
|
||||
* This function is called after a PCI bus error affecting
|
||||
* this device has been detected.
|
||||
*/
|
||||
static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
|
||||
pci_channel_state_t state)
|
||||
{
|
||||
struct adapter *adapter = pci_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
/* Stop all ports */
|
||||
for_each_port(adapter, i) {
|
||||
struct net_device *netdev = adapter->port[i];
|
||||
|
||||
if (netif_running(netdev))
|
||||
cxgb_close(netdev);
|
||||
}
|
||||
|
||||
if (is_offload(adapter) &&
|
||||
test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
|
||||
offload_close(&adapter->tdev);
|
||||
|
||||
/* Free sge resources */
|
||||
t3_free_sge_resources(adapter);
|
||||
|
||||
adapter->flags &= ~FULL_INIT_DONE;
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
||||
/* Request a slot slot reset. */
|
||||
return PCI_ERS_RESULT_NEED_RESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_io_slot_reset - called after the pci bus has been reset.
|
||||
* @pdev: Pointer to PCI device
|
||||
*
|
||||
* Restart the card from scratch, as if from a cold-boot.
|
||||
*/
|
||||
static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev)
|
||||
{
|
||||
struct adapter *adapter = pci_get_drvdata(pdev);
|
||||
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot re-enable PCI device after reset.\n");
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
t3_prep_adapter(adapter, adapter->params.info, 1);
|
||||
|
||||
return PCI_ERS_RESULT_RECOVERED;
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_io_resume - called when traffic can start flowing again.
|
||||
* @pdev: Pointer to PCI device
|
||||
*
|
||||
* This callback is called when the error recovery driver tells us that
|
||||
* its OK to resume normal operation.
|
||||
*/
|
||||
static void t3_io_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct adapter *adapter = pci_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
/* Restart the ports */
|
||||
for_each_port(adapter, i) {
|
||||
struct net_device *netdev = adapter->port[i];
|
||||
|
||||
if (netif_running(netdev)) {
|
||||
if (cxgb_open(netdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"can't bring device back up"
|
||||
" after reset\n");
|
||||
continue;
|
||||
}
|
||||
netif_device_attach(netdev);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_offload(adapter)) {
|
||||
__set_bit(OFFLOAD_DEVMAP_BIT, &adapter->registered_device_map);
|
||||
if (offload_open(adapter->port[0]))
|
||||
printk(KERN_WARNING
|
||||
"Could not bring back offload capabilities\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_error_handlers t3_err_handler = {
|
||||
.error_detected = t3_io_error_detected,
|
||||
.slot_reset = t3_io_slot_reset,
|
||||
.resume = t3_io_resume,
|
||||
};
|
||||
|
||||
static int __devinit cxgb_enable_msix(struct adapter *adap)
|
||||
{
|
||||
struct msix_entry entries[SGE_QSETS + 1];
|
||||
|
@ -2507,7 +2690,7 @@ static int __devinit init_one(struct pci_dev *pdev,
|
|||
err = -ENODEV;
|
||||
goto out_free_dev;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The card is now ready to go. If any errors occur during device
|
||||
* registration we do not fail the whole card but rather proceed only
|
||||
|
@ -2584,10 +2767,6 @@ static void __devexit remove_one(struct pci_dev *pdev)
|
|||
sysfs_remove_group(&adapter->port[0]->dev.kobj,
|
||||
&cxgb3_attr_group);
|
||||
|
||||
for_each_port(adapter, i)
|
||||
if (test_bit(i, &adapter->registered_device_map))
|
||||
unregister_netdev(adapter->port[i]);
|
||||
|
||||
if (is_offload(adapter)) {
|
||||
cxgb3_adapter_unofld(adapter);
|
||||
if (test_bit(OFFLOAD_DEVMAP_BIT,
|
||||
|
@ -2595,6 +2774,10 @@ static void __devexit remove_one(struct pci_dev *pdev)
|
|||
offload_close(&adapter->tdev);
|
||||
}
|
||||
|
||||
for_each_port(adapter, i)
|
||||
if (test_bit(i, &adapter->registered_device_map))
|
||||
unregister_netdev(adapter->port[i]);
|
||||
|
||||
t3_free_sge_resources(adapter);
|
||||
cxgb_disable_msi(adapter);
|
||||
|
||||
|
@ -2615,6 +2798,7 @@ static struct pci_driver driver = {
|
|||
.id_table = cxgb3_pci_tbl,
|
||||
.probe = init_one,
|
||||
.remove = __devexit_p(remove_one),
|
||||
.err_handler = &t3_err_handler,
|
||||
};
|
||||
|
||||
static int __init cxgb3_init_module(void)
|
||||
|
|
|
@ -403,8 +403,6 @@ static int cxgb_offload_ctl(struct t3cdev *tdev, unsigned int req, void *data)
|
|||
static int rx_offload_blackhole(struct t3cdev *dev, struct sk_buff **skbs,
|
||||
int n)
|
||||
{
|
||||
CH_ERR(tdev2adap(dev), "%d unexpected offload packets, first data %u\n",
|
||||
n, ntohl(*(__be32 *)skbs[0]->data));
|
||||
while (n--)
|
||||
dev_kfree_skb_any(skbs[n]);
|
||||
return 0;
|
||||
|
@ -488,7 +486,7 @@ static void t3_process_tid_release_list(struct work_struct *work)
|
|||
tid_release_task);
|
||||
struct sk_buff *skb;
|
||||
struct t3cdev *tdev = td->dev;
|
||||
|
||||
|
||||
|
||||
spin_lock_bh(&td->tid_release_lock);
|
||||
while (td->tid_release_list) {
|
||||
|
@ -634,6 +632,18 @@ static int do_l2t_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
|
|||
return CPL_RET_BUF_DONE;
|
||||
}
|
||||
|
||||
static int do_rte_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_rte_write_rpl *rpl = cplhdr(skb);
|
||||
|
||||
if (rpl->status != CPL_ERR_NONE)
|
||||
printk(KERN_ERR
|
||||
"Unexpected RTE_WRITE_RPL status %u for entry %u\n",
|
||||
rpl->status, GET_TID(rpl));
|
||||
|
||||
return CPL_RET_BUF_DONE;
|
||||
}
|
||||
|
||||
static int do_act_open_rpl(struct t3cdev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_act_open_rpl *rpl = cplhdr(skb);
|
||||
|
@ -1004,7 +1014,7 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
|
|||
if (!is_offloading(olddev))
|
||||
return;
|
||||
if (!is_offloading(newdev)) {
|
||||
printk(KERN_WARNING "%s: Redirect to non-offload"
|
||||
printk(KERN_WARNING "%s: Redirect to non-offload "
|
||||
"device ignored.\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
@ -1257,6 +1267,7 @@ void __init cxgb3_offload_init(void)
|
|||
|
||||
t3_register_cpl_handler(CPL_SMT_WRITE_RPL, do_smt_write_rpl);
|
||||
t3_register_cpl_handler(CPL_L2T_WRITE_RPL, do_l2t_write_rpl);
|
||||
t3_register_cpl_handler(CPL_RTE_WRITE_RPL, do_rte_write_rpl);
|
||||
t3_register_cpl_handler(CPL_PASS_OPEN_RPL, do_stid_rpl);
|
||||
t3_register_cpl_handler(CPL_CLOSE_LISTSRV_RPL, do_stid_rpl);
|
||||
t3_register_cpl_handler(CPL_PASS_ACCEPT_REQ, do_cr);
|
||||
|
|
|
@ -76,14 +76,14 @@
|
|||
#define FW_WROPCODE_MNGT 0x1D
|
||||
#define FW_MNGTOPCODE_PKTSCHED_SET 0x00
|
||||
|
||||
/* Maximum size of a WR sent from the host, limited by the SGE.
|
||||
/* Maximum size of a WR sent from the host, limited by the SGE.
|
||||
*
|
||||
* Note: WR coming from ULP or TP are only limited by CIM.
|
||||
* Note: WR coming from ULP or TP are only limited by CIM.
|
||||
*/
|
||||
#define FW_WR_SIZE 128
|
||||
|
||||
/* Maximum number of outstanding WRs sent from the host. Value must be
|
||||
* programmed in the CTRL/TUNNEL/QP SGE Egress Context and used by
|
||||
* programmed in the CTRL/TUNNEL/QP SGE Egress Context and used by
|
||||
* offload modules to limit the number of WRs per connection.
|
||||
*/
|
||||
#define FW_T3_WR_NUM 16
|
||||
|
@ -99,7 +99,7 @@
|
|||
* queues must start at SGE Egress Context FW_TUNNEL_SGEEC_START and must
|
||||
* start at 'TID' (or 'uP Token') FW_TUNNEL_TID_START.
|
||||
*
|
||||
* Ingress Traffic (e.g. DMA completion credit) for TUNNEL Queue[i] is sent
|
||||
* Ingress Traffic (e.g. DMA completion credit) for TUNNEL Queue[i] is sent
|
||||
* to RESP Queue[i].
|
||||
*/
|
||||
#define FW_TUNNEL_NUM 8
|
||||
|
@ -116,10 +116,10 @@
|
|||
#define FW_CTRL_SGEEC_START 65528
|
||||
#define FW_CTRL_TID_START 65536
|
||||
|
||||
/* FW_OFLD_NUM corresponds to the number of supported OFFLOAD Queues. These
|
||||
* queues must start at SGE Egress Context FW_OFLD_SGEEC_START.
|
||||
*
|
||||
* Note: the 'uP Token' in the SGE Egress Context fields is irrelevant for
|
||||
/* FW_OFLD_NUM corresponds to the number of supported OFFLOAD Queues. These
|
||||
* queues must start at SGE Egress Context FW_OFLD_SGEEC_START.
|
||||
*
|
||||
* Note: the 'uP Token' in the SGE Egress Context fields is irrelevant for
|
||||
* OFFLOAD Queues, as the host is responsible for providing the correct TID in
|
||||
* every WR.
|
||||
*
|
||||
|
@ -129,14 +129,14 @@
|
|||
#define FW_OFLD_SGEEC_START 0
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define FW_RI_NUM 1
|
||||
#define FW_RI_SGEEC_START 65527
|
||||
#define FW_RI_TID_START 65552
|
||||
|
||||
/*
|
||||
* The RX_PKT_TID
|
||||
* The RX_PKT_TID
|
||||
*/
|
||||
#define FW_RX_PKT_NUM 1
|
||||
#define FW_RX_PKT_TID_START 65553
|
||||
|
|
|
@ -337,7 +337,7 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
|
|||
atomic_set(&e->refcnt, 1);
|
||||
neigh_replace(e, neigh);
|
||||
if (neigh->dev->priv_flags & IFF_802_1Q_VLAN)
|
||||
e->vlan = VLAN_DEV_INFO(neigh->dev)->vlan_id;
|
||||
e->vlan = vlan_dev_info(neigh->dev)->vlan_id;
|
||||
else
|
||||
e->vlan = VLAN_NONE;
|
||||
spin_unlock(&e->lock);
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
#define A_SG_CONTROL 0x0
|
||||
|
||||
#define S_CONGMODE 29
|
||||
#define V_CONGMODE(x) ((x) << S_CONGMODE)
|
||||
#define F_CONGMODE V_CONGMODE(1U)
|
||||
|
||||
#define S_TNLFLMODE 28
|
||||
#define V_TNLFLMODE(x) ((x) << S_TNLFLMODE)
|
||||
#define F_TNLFLMODE V_TNLFLMODE(1U)
|
||||
|
||||
#define S_FATLPERREN 27
|
||||
#define V_FATLPERREN(x) ((x) << S_FATLPERREN)
|
||||
#define F_FATLPERREN V_FATLPERREN(1U)
|
||||
|
||||
#define S_DROPPKT 20
|
||||
#define V_DROPPKT(x) ((x) << S_DROPPKT)
|
||||
#define F_DROPPKT V_DROPPKT(1U)
|
||||
|
@ -172,6 +184,64 @@
|
|||
|
||||
#define A_SG_INT_CAUSE 0x5c
|
||||
|
||||
#define S_HIRCQPARITYERROR 31
|
||||
#define V_HIRCQPARITYERROR(x) ((x) << S_HIRCQPARITYERROR)
|
||||
#define F_HIRCQPARITYERROR V_HIRCQPARITYERROR(1U)
|
||||
|
||||
#define S_LORCQPARITYERROR 30
|
||||
#define V_LORCQPARITYERROR(x) ((x) << S_LORCQPARITYERROR)
|
||||
#define F_LORCQPARITYERROR V_LORCQPARITYERROR(1U)
|
||||
|
||||
#define S_HIDRBPARITYERROR 29
|
||||
#define V_HIDRBPARITYERROR(x) ((x) << S_HIDRBPARITYERROR)
|
||||
#define F_HIDRBPARITYERROR V_HIDRBPARITYERROR(1U)
|
||||
|
||||
#define S_LODRBPARITYERROR 28
|
||||
#define V_LODRBPARITYERROR(x) ((x) << S_LODRBPARITYERROR)
|
||||
#define F_LODRBPARITYERROR V_LODRBPARITYERROR(1U)
|
||||
|
||||
#define S_FLPARITYERROR 22
|
||||
#define M_FLPARITYERROR 0x3f
|
||||
#define V_FLPARITYERROR(x) ((x) << S_FLPARITYERROR)
|
||||
#define G_FLPARITYERROR(x) (((x) >> S_FLPARITYERROR) & M_FLPARITYERROR)
|
||||
|
||||
#define S_ITPARITYERROR 20
|
||||
#define M_ITPARITYERROR 0x3
|
||||
#define V_ITPARITYERROR(x) ((x) << S_ITPARITYERROR)
|
||||
#define G_ITPARITYERROR(x) (((x) >> S_ITPARITYERROR) & M_ITPARITYERROR)
|
||||
|
||||
#define S_IRPARITYERROR 19
|
||||
#define V_IRPARITYERROR(x) ((x) << S_IRPARITYERROR)
|
||||
#define F_IRPARITYERROR V_IRPARITYERROR(1U)
|
||||
|
||||
#define S_RCPARITYERROR 18
|
||||
#define V_RCPARITYERROR(x) ((x) << S_RCPARITYERROR)
|
||||
#define F_RCPARITYERROR V_RCPARITYERROR(1U)
|
||||
|
||||
#define S_OCPARITYERROR 17
|
||||
#define V_OCPARITYERROR(x) ((x) << S_OCPARITYERROR)
|
||||
#define F_OCPARITYERROR V_OCPARITYERROR(1U)
|
||||
|
||||
#define S_CPPARITYERROR 16
|
||||
#define V_CPPARITYERROR(x) ((x) << S_CPPARITYERROR)
|
||||
#define F_CPPARITYERROR V_CPPARITYERROR(1U)
|
||||
|
||||
#define S_R_REQ_FRAMINGERROR 15
|
||||
#define V_R_REQ_FRAMINGERROR(x) ((x) << S_R_REQ_FRAMINGERROR)
|
||||
#define F_R_REQ_FRAMINGERROR V_R_REQ_FRAMINGERROR(1U)
|
||||
|
||||
#define S_UC_REQ_FRAMINGERROR 14
|
||||
#define V_UC_REQ_FRAMINGERROR(x) ((x) << S_UC_REQ_FRAMINGERROR)
|
||||
#define F_UC_REQ_FRAMINGERROR V_UC_REQ_FRAMINGERROR(1U)
|
||||
|
||||
#define S_HICTLDRBDROPERR 13
|
||||
#define V_HICTLDRBDROPERR(x) ((x) << S_HICTLDRBDROPERR)
|
||||
#define F_HICTLDRBDROPERR V_HICTLDRBDROPERR(1U)
|
||||
|
||||
#define S_LOCTLDRBDROPERR 12
|
||||
#define V_LOCTLDRBDROPERR(x) ((x) << S_LOCTLDRBDROPERR)
|
||||
#define F_LOCTLDRBDROPERR V_LOCTLDRBDROPERR(1U)
|
||||
|
||||
#define S_HIPIODRBDROPERR 11
|
||||
#define V_HIPIODRBDROPERR(x) ((x) << S_HIPIODRBDROPERR)
|
||||
#define F_HIPIODRBDROPERR V_HIPIODRBDROPERR(1U)
|
||||
|
@ -286,6 +356,10 @@
|
|||
|
||||
#define A_PCIX_CFG 0x88
|
||||
|
||||
#define S_DMASTOPEN 19
|
||||
#define V_DMASTOPEN(x) ((x) << S_DMASTOPEN)
|
||||
#define F_DMASTOPEN V_DMASTOPEN(1U)
|
||||
|
||||
#define S_CLIDECEN 18
|
||||
#define V_CLIDECEN(x) ((x) << S_CLIDECEN)
|
||||
#define F_CLIDECEN V_CLIDECEN(1U)
|
||||
|
@ -313,6 +387,22 @@
|
|||
|
||||
#define V_BISTERR(x) ((x) << S_BISTERR)
|
||||
|
||||
#define S_TXPARERR 18
|
||||
#define V_TXPARERR(x) ((x) << S_TXPARERR)
|
||||
#define F_TXPARERR V_TXPARERR(1U)
|
||||
|
||||
#define S_RXPARERR 17
|
||||
#define V_RXPARERR(x) ((x) << S_RXPARERR)
|
||||
#define F_RXPARERR V_RXPARERR(1U)
|
||||
|
||||
#define S_RETRYLUTPARERR 16
|
||||
#define V_RETRYLUTPARERR(x) ((x) << S_RETRYLUTPARERR)
|
||||
#define F_RETRYLUTPARERR V_RETRYLUTPARERR(1U)
|
||||
|
||||
#define S_RETRYBUFPARERR 15
|
||||
#define V_RETRYBUFPARERR(x) ((x) << S_RETRYBUFPARERR)
|
||||
#define F_RETRYBUFPARERR V_RETRYBUFPARERR(1U)
|
||||
|
||||
#define S_PCIE_MSIXPARERR 12
|
||||
#define M_PCIE_MSIXPARERR 0x7
|
||||
|
||||
|
@ -348,6 +438,10 @@
|
|||
|
||||
#define A_PCIE_INT_CAUSE 0x84
|
||||
|
||||
#define S_PCIE_DMASTOPEN 24
|
||||
#define V_PCIE_DMASTOPEN(x) ((x) << S_PCIE_DMASTOPEN)
|
||||
#define F_PCIE_DMASTOPEN V_PCIE_DMASTOPEN(1U)
|
||||
|
||||
#define A_PCIE_CFG 0x88
|
||||
|
||||
#define S_PCIE_CLIDECEN 16
|
||||
|
@ -741,6 +835,54 @@
|
|||
|
||||
#define A_CIM_HOST_INT_ENABLE 0x298
|
||||
|
||||
#define S_DTAGPARERR 28
|
||||
#define V_DTAGPARERR(x) ((x) << S_DTAGPARERR)
|
||||
#define F_DTAGPARERR V_DTAGPARERR(1U)
|
||||
|
||||
#define S_ITAGPARERR 27
|
||||
#define V_ITAGPARERR(x) ((x) << S_ITAGPARERR)
|
||||
#define F_ITAGPARERR V_ITAGPARERR(1U)
|
||||
|
||||
#define S_IBQTPPARERR 26
|
||||
#define V_IBQTPPARERR(x) ((x) << S_IBQTPPARERR)
|
||||
#define F_IBQTPPARERR V_IBQTPPARERR(1U)
|
||||
|
||||
#define S_IBQULPPARERR 25
|
||||
#define V_IBQULPPARERR(x) ((x) << S_IBQULPPARERR)
|
||||
#define F_IBQULPPARERR V_IBQULPPARERR(1U)
|
||||
|
||||
#define S_IBQSGEHIPARERR 24
|
||||
#define V_IBQSGEHIPARERR(x) ((x) << S_IBQSGEHIPARERR)
|
||||
#define F_IBQSGEHIPARERR V_IBQSGEHIPARERR(1U)
|
||||
|
||||
#define S_IBQSGELOPARERR 23
|
||||
#define V_IBQSGELOPARERR(x) ((x) << S_IBQSGELOPARERR)
|
||||
#define F_IBQSGELOPARERR V_IBQSGELOPARERR(1U)
|
||||
|
||||
#define S_OBQULPLOPARERR 22
|
||||
#define V_OBQULPLOPARERR(x) ((x) << S_OBQULPLOPARERR)
|
||||
#define F_OBQULPLOPARERR V_OBQULPLOPARERR(1U)
|
||||
|
||||
#define S_OBQULPHIPARERR 21
|
||||
#define V_OBQULPHIPARERR(x) ((x) << S_OBQULPHIPARERR)
|
||||
#define F_OBQULPHIPARERR V_OBQULPHIPARERR(1U)
|
||||
|
||||
#define S_OBQSGEPARERR 20
|
||||
#define V_OBQSGEPARERR(x) ((x) << S_OBQSGEPARERR)
|
||||
#define F_OBQSGEPARERR V_OBQSGEPARERR(1U)
|
||||
|
||||
#define S_DCACHEPARERR 19
|
||||
#define V_DCACHEPARERR(x) ((x) << S_DCACHEPARERR)
|
||||
#define F_DCACHEPARERR V_DCACHEPARERR(1U)
|
||||
|
||||
#define S_ICACHEPARERR 18
|
||||
#define V_ICACHEPARERR(x) ((x) << S_ICACHEPARERR)
|
||||
#define F_ICACHEPARERR V_ICACHEPARERR(1U)
|
||||
|
||||
#define S_DRAMPARERR 17
|
||||
#define V_DRAMPARERR(x) ((x) << S_DRAMPARERR)
|
||||
#define F_DRAMPARERR V_DRAMPARERR(1U)
|
||||
|
||||
#define A_CIM_HOST_INT_CAUSE 0x29c
|
||||
|
||||
#define S_BLKWRPLINT 12
|
||||
|
@ -799,8 +941,42 @@
|
|||
|
||||
#define A_CIM_HOST_ACC_DATA 0x2b4
|
||||
|
||||
#define A_CIM_IBQ_DBG_CFG 0x2c0
|
||||
|
||||
#define S_IBQDBGADDR 16
|
||||
#define M_IBQDBGADDR 0x1ff
|
||||
#define V_IBQDBGADDR(x) ((x) << S_IBQDBGADDR)
|
||||
#define G_IBQDBGADDR(x) (((x) >> S_IBQDBGADDR) & M_IBQDBGADDR)
|
||||
|
||||
#define S_IBQDBGQID 3
|
||||
#define M_IBQDBGQID 0x3
|
||||
#define V_IBQDBGQID(x) ((x) << S_IBQDBGQID)
|
||||
#define G_IBQDBGQID(x) (((x) >> S_IBQDBGQID) & M_IBQDBGQID)
|
||||
|
||||
#define S_IBQDBGWR 2
|
||||
#define V_IBQDBGWR(x) ((x) << S_IBQDBGWR)
|
||||
#define F_IBQDBGWR V_IBQDBGWR(1U)
|
||||
|
||||
#define S_IBQDBGBUSY 1
|
||||
#define V_IBQDBGBUSY(x) ((x) << S_IBQDBGBUSY)
|
||||
#define F_IBQDBGBUSY V_IBQDBGBUSY(1U)
|
||||
|
||||
#define S_IBQDBGEN 0
|
||||
#define V_IBQDBGEN(x) ((x) << S_IBQDBGEN)
|
||||
#define F_IBQDBGEN V_IBQDBGEN(1U)
|
||||
|
||||
#define A_CIM_IBQ_DBG_DATA 0x2c8
|
||||
|
||||
#define A_TP_IN_CONFIG 0x300
|
||||
|
||||
#define S_RXFBARBPRIO 25
|
||||
#define V_RXFBARBPRIO(x) ((x) << S_RXFBARBPRIO)
|
||||
#define F_RXFBARBPRIO V_RXFBARBPRIO(1U)
|
||||
|
||||
#define S_TXFBARBPRIO 24
|
||||
#define V_TXFBARBPRIO(x) ((x) << S_TXFBARBPRIO)
|
||||
#define F_TXFBARBPRIO V_TXFBARBPRIO(1U)
|
||||
|
||||
#define S_NICMODE 14
|
||||
#define V_NICMODE(x) ((x) << S_NICMODE)
|
||||
#define F_NICMODE V_NICMODE(1U)
|
||||
|
@ -965,8 +1141,30 @@
|
|||
#define V_LOCKTID(x) ((x) << S_LOCKTID)
|
||||
#define F_LOCKTID V_LOCKTID(1U)
|
||||
|
||||
#define S_TABLELATENCYDELTA 0
|
||||
#define M_TABLELATENCYDELTA 0xf
|
||||
#define V_TABLELATENCYDELTA(x) ((x) << S_TABLELATENCYDELTA)
|
||||
#define G_TABLELATENCYDELTA(x) \
|
||||
(((x) >> S_TABLELATENCYDELTA) & M_TABLELATENCYDELTA)
|
||||
|
||||
#define A_TP_PC_CONFIG2 0x34c
|
||||
|
||||
#define S_DISBLEDAPARBIT0 15
|
||||
#define V_DISBLEDAPARBIT0(x) ((x) << S_DISBLEDAPARBIT0)
|
||||
#define F_DISBLEDAPARBIT0 V_DISBLEDAPARBIT0(1U)
|
||||
|
||||
#define S_ENABLEARPMISS 13
|
||||
#define V_ENABLEARPMISS(x) ((x) << S_ENABLEARPMISS)
|
||||
#define F_ENABLEARPMISS V_ENABLEARPMISS(1U)
|
||||
|
||||
#define S_ENABLENONOFDTNLSYN 12
|
||||
#define V_ENABLENONOFDTNLSYN(x) ((x) << S_ENABLENONOFDTNLSYN)
|
||||
#define F_ENABLENONOFDTNLSYN V_ENABLENONOFDTNLSYN(1U)
|
||||
|
||||
#define S_ENABLEIPV6RSS 11
|
||||
#define V_ENABLEIPV6RSS(x) ((x) << S_ENABLEIPV6RSS)
|
||||
#define F_ENABLEIPV6RSS V_ENABLEIPV6RSS(1U)
|
||||
|
||||
#define S_CHDRAFULL 4
|
||||
#define V_CHDRAFULL(x) ((x) << S_CHDRAFULL)
|
||||
#define F_CHDRAFULL V_CHDRAFULL(1U)
|
||||
|
@ -1018,6 +1216,12 @@
|
|||
|
||||
#define A_TP_PARA_REG4 0x370
|
||||
|
||||
#define A_TP_PARA_REG5 0x374
|
||||
|
||||
#define S_RXDDPOFFINIT 3
|
||||
#define V_RXDDPOFFINIT(x) ((x) << S_RXDDPOFFINIT)
|
||||
#define F_RXDDPOFFINIT V_RXDDPOFFINIT(1U)
|
||||
|
||||
#define A_TP_PARA_REG6 0x378
|
||||
|
||||
#define S_T3A_ENABLEESND 13
|
||||
|
@ -1138,6 +1342,10 @@
|
|||
#define V_TNLLKPEN(x) ((x) << S_TNLLKPEN)
|
||||
#define F_TNLLKPEN V_TNLLKPEN(1U)
|
||||
|
||||
#define S_RRCPLMAPEN 7
|
||||
#define V_RRCPLMAPEN(x) ((x) << S_RRCPLMAPEN)
|
||||
#define F_RRCPLMAPEN V_RRCPLMAPEN(1U)
|
||||
|
||||
#define S_RRCPLCPUSIZE 4
|
||||
#define M_RRCPLCPUSIZE 0x7
|
||||
#define V_RRCPLCPUSIZE(x) ((x) << S_RRCPLCPUSIZE)
|
||||
|
@ -1146,6 +1354,10 @@
|
|||
#define V_RQFEEDBACKENABLE(x) ((x) << S_RQFEEDBACKENABLE)
|
||||
#define F_RQFEEDBACKENABLE V_RQFEEDBACKENABLE(1U)
|
||||
|
||||
#define S_HASHTOEPLITZ 2
|
||||
#define V_HASHTOEPLITZ(x) ((x) << S_HASHTOEPLITZ)
|
||||
#define F_HASHTOEPLITZ V_HASHTOEPLITZ(1U)
|
||||
|
||||
#define S_DISABLE 0
|
||||
|
||||
#define A_TP_TM_PIO_ADDR 0x418
|
||||
|
@ -1198,6 +1410,22 @@
|
|||
|
||||
#define A_TP_INT_ENABLE 0x470
|
||||
|
||||
#define S_FLMTXFLSTEMPTY 30
|
||||
#define V_FLMTXFLSTEMPTY(x) ((x) << S_FLMTXFLSTEMPTY)
|
||||
#define F_FLMTXFLSTEMPTY V_FLMTXFLSTEMPTY(1U)
|
||||
|
||||
#define S_FLMRXFLSTEMPTY 29
|
||||
#define V_FLMRXFLSTEMPTY(x) ((x) << S_FLMRXFLSTEMPTY)
|
||||
#define F_FLMRXFLSTEMPTY V_FLMRXFLSTEMPTY(1U)
|
||||
|
||||
#define S_ARPLUTPERR 26
|
||||
#define V_ARPLUTPERR(x) ((x) << S_ARPLUTPERR)
|
||||
#define F_ARPLUTPERR V_ARPLUTPERR(1U)
|
||||
|
||||
#define S_CMCACHEPERR 24
|
||||
#define V_CMCACHEPERR(x) ((x) << S_CMCACHEPERR)
|
||||
#define F_CMCACHEPERR V_CMCACHEPERR(1U)
|
||||
|
||||
#define A_TP_INT_CAUSE 0x474
|
||||
|
||||
#define A_TP_TX_MOD_Q1_Q0_RATE_LIMIT 0x8
|
||||
|
@ -1241,9 +1469,37 @@
|
|||
|
||||
#define A_ULPRX_INT_ENABLE 0x504
|
||||
|
||||
#define S_PARERR 0
|
||||
#define V_PARERR(x) ((x) << S_PARERR)
|
||||
#define F_PARERR V_PARERR(1U)
|
||||
#define S_DATASELFRAMEERR0 7
|
||||
#define V_DATASELFRAMEERR0(x) ((x) << S_DATASELFRAMEERR0)
|
||||
#define F_DATASELFRAMEERR0 V_DATASELFRAMEERR0(1U)
|
||||
|
||||
#define S_DATASELFRAMEERR1 6
|
||||
#define V_DATASELFRAMEERR1(x) ((x) << S_DATASELFRAMEERR1)
|
||||
#define F_DATASELFRAMEERR1 V_DATASELFRAMEERR1(1U)
|
||||
|
||||
#define S_PCMDMUXPERR 5
|
||||
#define V_PCMDMUXPERR(x) ((x) << S_PCMDMUXPERR)
|
||||
#define F_PCMDMUXPERR V_PCMDMUXPERR(1U)
|
||||
|
||||
#define S_ARBFPERR 4
|
||||
#define V_ARBFPERR(x) ((x) << S_ARBFPERR)
|
||||
#define F_ARBFPERR V_ARBFPERR(1U)
|
||||
|
||||
#define S_ARBPF0PERR 3
|
||||
#define V_ARBPF0PERR(x) ((x) << S_ARBPF0PERR)
|
||||
#define F_ARBPF0PERR V_ARBPF0PERR(1U)
|
||||
|
||||
#define S_ARBPF1PERR 2
|
||||
#define V_ARBPF1PERR(x) ((x) << S_ARBPF1PERR)
|
||||
#define F_ARBPF1PERR V_ARBPF1PERR(1U)
|
||||
|
||||
#define S_PARERRPCMD 1
|
||||
#define V_PARERRPCMD(x) ((x) << S_PARERRPCMD)
|
||||
#define F_PARERRPCMD V_PARERRPCMD(1U)
|
||||
|
||||
#define S_PARERRDATA 0
|
||||
#define V_PARERRDATA(x) ((x) << S_PARERRDATA)
|
||||
#define F_PARERRDATA V_PARERRDATA(1U)
|
||||
|
||||
#define A_ULPRX_INT_CAUSE 0x508
|
||||
|
||||
|
@ -1291,6 +1547,10 @@
|
|||
|
||||
#define A_ULPTX_CONFIG 0x580
|
||||
|
||||
#define S_CFG_CQE_SOP_MASK 1
|
||||
#define V_CFG_CQE_SOP_MASK(x) ((x) << S_CFG_CQE_SOP_MASK)
|
||||
#define F_CFG_CQE_SOP_MASK V_CFG_CQE_SOP_MASK(1U)
|
||||
|
||||
#define S_CFG_RR_ARB 0
|
||||
#define V_CFG_RR_ARB(x) ((x) << S_CFG_RR_ARB)
|
||||
#define F_CFG_RR_ARB V_CFG_RR_ARB(1U)
|
||||
|
@ -1537,6 +1797,10 @@
|
|||
|
||||
#define A_CPL_INTR_ENABLE 0x650
|
||||
|
||||
#define S_CIM_OP_MAP_PERR 5
|
||||
#define V_CIM_OP_MAP_PERR(x) ((x) << S_CIM_OP_MAP_PERR)
|
||||
#define F_CIM_OP_MAP_PERR V_CIM_OP_MAP_PERR(1U)
|
||||
|
||||
#define S_CIM_OVFL_ERROR 4
|
||||
#define V_CIM_OVFL_ERROR(x) ((x) << S_CIM_OVFL_ERROR)
|
||||
#define F_CIM_OVFL_ERROR V_CIM_OVFL_ERROR(1U)
|
||||
|
|
|
@ -91,6 +91,10 @@ struct rx_desc {
|
|||
|
||||
struct tx_sw_desc { /* SW state per Tx descriptor */
|
||||
struct sk_buff *skb;
|
||||
u8 eop; /* set if last descriptor for packet */
|
||||
u8 addr_idx; /* buffer index of first SGL entry in descriptor */
|
||||
u8 fragidx; /* first page fragment associated with descriptor */
|
||||
s8 sflit; /* start flit of first SGL entry in descriptor */
|
||||
};
|
||||
|
||||
struct rx_sw_desc { /* SW state per Rx descriptor */
|
||||
|
@ -109,13 +113,6 @@ struct rsp_desc { /* response queue descriptor */
|
|||
u8 intr_gen;
|
||||
};
|
||||
|
||||
struct unmap_info { /* packet unmapping info, overlays skb->cb */
|
||||
int sflit; /* start flit of first SGL entry in Tx descriptor */
|
||||
u16 fragidx; /* first page fragment in current Tx descriptor */
|
||||
u16 addr_idx; /* buffer index of first SGL entry in descriptor */
|
||||
u32 len; /* mapped length of skb main body */
|
||||
};
|
||||
|
||||
/*
|
||||
* Holds unmapping information for Tx packets that need deferred unmapping.
|
||||
* This structure lives at skb->head and must be allocated by callers.
|
||||
|
@ -177,6 +174,7 @@ static inline struct sge_qset *txq_to_qset(const struct sge_txq *q, int qidx)
|
|||
static inline void refill_rspq(struct adapter *adapter,
|
||||
const struct sge_rspq *q, unsigned int credits)
|
||||
{
|
||||
rmb();
|
||||
t3_write_reg(adapter, A_SG_RSPQ_CREDIT_RETURN,
|
||||
V_RSPQ(q->cntxt_id) | V_CREDITS(credits));
|
||||
}
|
||||
|
@ -209,32 +207,36 @@ static inline int need_skb_unmap(void)
|
|||
*
|
||||
* Unmap the main body of an sk_buff and its page fragments, if any.
|
||||
* Because of the fairly complicated structure of our SGLs and the desire
|
||||
* to conserve space for metadata, we keep the information necessary to
|
||||
* unmap an sk_buff partly in the sk_buff itself (in its cb), and partly
|
||||
* in the Tx descriptors (the physical addresses of the various data
|
||||
* buffers). The send functions initialize the state in skb->cb so we
|
||||
* can unmap the buffers held in the first Tx descriptor here, and we
|
||||
* have enough information at this point to update the state for the next
|
||||
* Tx descriptor.
|
||||
* to conserve space for metadata, the information necessary to unmap an
|
||||
* sk_buff is spread across the sk_buff itself (buffer lengths), the HW Tx
|
||||
* descriptors (the physical addresses of the various data buffers), and
|
||||
* the SW descriptor state (assorted indices). The send functions
|
||||
* initialize the indices for the first packet descriptor so we can unmap
|
||||
* the buffers held in the first Tx descriptor here, and we have enough
|
||||
* information at this point to set the state for the next Tx descriptor.
|
||||
*
|
||||
* Note that it is possible to clean up the first descriptor of a packet
|
||||
* before the send routines have written the next descriptors, but this
|
||||
* race does not cause any problem. We just end up writing the unmapping
|
||||
* info for the descriptor first.
|
||||
*/
|
||||
static inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q,
|
||||
unsigned int cidx, struct pci_dev *pdev)
|
||||
{
|
||||
const struct sg_ent *sgp;
|
||||
struct unmap_info *ui = (struct unmap_info *)skb->cb;
|
||||
int nfrags, frag_idx, curflit, j = ui->addr_idx;
|
||||
struct tx_sw_desc *d = &q->sdesc[cidx];
|
||||
int nfrags, frag_idx, curflit, j = d->addr_idx;
|
||||
|
||||
sgp = (struct sg_ent *)&q->desc[cidx].flit[ui->sflit];
|
||||
sgp = (struct sg_ent *)&q->desc[cidx].flit[d->sflit];
|
||||
frag_idx = d->fragidx;
|
||||
|
||||
if (ui->len) {
|
||||
pci_unmap_single(pdev, be64_to_cpu(sgp->addr[0]), ui->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
ui->len = 0; /* so we know for next descriptor for this skb */
|
||||
if (frag_idx == 0 && skb_headlen(skb)) {
|
||||
pci_unmap_single(pdev, be64_to_cpu(sgp->addr[0]),
|
||||
skb_headlen(skb), PCI_DMA_TODEVICE);
|
||||
j = 1;
|
||||
}
|
||||
|
||||
frag_idx = ui->fragidx;
|
||||
curflit = ui->sflit + 1 + j;
|
||||
curflit = d->sflit + 1 + j;
|
||||
nfrags = skb_shinfo(skb)->nr_frags;
|
||||
|
||||
while (frag_idx < nfrags && curflit < WR_FLITS) {
|
||||
|
@ -250,10 +252,11 @@ static inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q,
|
|||
frag_idx++;
|
||||
}
|
||||
|
||||
if (frag_idx < nfrags) { /* SGL continues into next Tx descriptor */
|
||||
ui->fragidx = frag_idx;
|
||||
ui->addr_idx = j;
|
||||
ui->sflit = curflit - WR_FLITS - j; /* sflit can be -1 */
|
||||
if (frag_idx < nfrags) { /* SGL continues into next Tx descriptor */
|
||||
d = cidx + 1 == q->size ? q->sdesc : d + 1;
|
||||
d->fragidx = frag_idx;
|
||||
d->addr_idx = j;
|
||||
d->sflit = curflit - WR_FLITS - j; /* sflit can be -1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +284,7 @@ static void free_tx_desc(struct adapter *adapter, struct sge_txq *q,
|
|||
if (d->skb) { /* an SGL is present */
|
||||
if (need_unmap)
|
||||
unmap_skb(d->skb, q, cidx, pdev);
|
||||
if (d->skb->priority == cidx)
|
||||
if (d->eop)
|
||||
kfree_skb(d->skb);
|
||||
}
|
||||
++d;
|
||||
|
@ -456,7 +459,7 @@ nomem: q->alloc_failed++;
|
|||
}
|
||||
q->credits++;
|
||||
}
|
||||
|
||||
wmb();
|
||||
t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
|
||||
}
|
||||
|
||||
|
@ -912,15 +915,13 @@ static void write_wr_hdr_sgl(unsigned int ndesc, struct sk_buff *skb,
|
|||
|
||||
sd->skb = skb;
|
||||
if (need_skb_unmap()) {
|
||||
struct unmap_info *ui = (struct unmap_info *)skb->cb;
|
||||
|
||||
ui->fragidx = 0;
|
||||
ui->addr_idx = 0;
|
||||
ui->sflit = flits;
|
||||
sd->fragidx = 0;
|
||||
sd->addr_idx = 0;
|
||||
sd->sflit = flits;
|
||||
}
|
||||
|
||||
if (likely(ndesc == 1)) {
|
||||
skb->priority = pidx;
|
||||
sd->eop = 1;
|
||||
wrp->wr_hi = htonl(F_WR_SOP | F_WR_EOP | V_WR_DATATYPE(1) |
|
||||
V_WR_SGLSFLT(flits)) | wr_hi;
|
||||
wmb();
|
||||
|
@ -948,6 +949,7 @@ static void write_wr_hdr_sgl(unsigned int ndesc, struct sk_buff *skb,
|
|||
|
||||
fp += avail;
|
||||
d++;
|
||||
sd->eop = 0;
|
||||
sd++;
|
||||
if (++pidx == q->size) {
|
||||
pidx = 0;
|
||||
|
@ -966,7 +968,7 @@ static void write_wr_hdr_sgl(unsigned int ndesc, struct sk_buff *skb,
|
|||
wr_gen2(d, gen);
|
||||
flits = 1;
|
||||
}
|
||||
skb->priority = pidx;
|
||||
sd->eop = 1;
|
||||
wrp->wr_hi |= htonl(F_WR_EOP);
|
||||
wmb();
|
||||
wp->wr_lo = htonl(V_WR_LEN(WR_FLITS) | V_WR_GEN(ogen)) | wr_lo;
|
||||
|
@ -1051,8 +1053,6 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
|
|||
|
||||
sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
|
||||
sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev);
|
||||
if (need_skb_unmap())
|
||||
((struct unmap_info *)skb->cb)->len = skb_headlen(skb);
|
||||
|
||||
write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen,
|
||||
htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl),
|
||||
|
@ -1354,6 +1354,7 @@ static void restart_ctrlq(unsigned long data)
|
|||
}
|
||||
|
||||
spin_unlock(&q->lock);
|
||||
wmb();
|
||||
t3_write_reg(qs->adap, A_SG_KDOORBELL,
|
||||
F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
|
||||
}
|
||||
|
@ -1363,7 +1364,12 @@ static void restart_ctrlq(unsigned long data)
|
|||
*/
|
||||
int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
|
||||
{
|
||||
return ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
|
||||
int ret;
|
||||
local_bh_disable();
|
||||
ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
|
||||
local_bh_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1380,13 +1386,14 @@ static void deferred_unmap_destructor(struct sk_buff *skb)
|
|||
const dma_addr_t *p;
|
||||
const struct skb_shared_info *si;
|
||||
const struct deferred_unmap_info *dui;
|
||||
const struct unmap_info *ui = (struct unmap_info *)skb->cb;
|
||||
|
||||
dui = (struct deferred_unmap_info *)skb->head;
|
||||
p = dui->addr;
|
||||
|
||||
if (ui->len)
|
||||
pci_unmap_single(dui->pdev, *p++, ui->len, PCI_DMA_TODEVICE);
|
||||
if (skb->tail - skb->transport_header)
|
||||
pci_unmap_single(dui->pdev, *p++,
|
||||
skb->tail - skb->transport_header,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
si = skb_shinfo(skb);
|
||||
for (i = 0; i < si->nr_frags; i++)
|
||||
|
@ -1451,8 +1458,6 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
|
|||
if (need_skb_unmap()) {
|
||||
setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
|
||||
skb->destructor = deferred_unmap_destructor;
|
||||
((struct unmap_info *)skb->cb)->len = (skb->tail -
|
||||
skb->transport_header);
|
||||
}
|
||||
|
||||
write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits,
|
||||
|
@ -1574,6 +1579,7 @@ static void restart_offloadq(unsigned long data)
|
|||
set_bit(TXQ_RUNNING, &q->flags);
|
||||
set_bit(TXQ_LAST_PKT_DB, &q->flags);
|
||||
#endif
|
||||
wmb();
|
||||
t3_write_reg(adap, A_SG_KDOORBELL,
|
||||
F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
|
||||
}
|
||||
|
@ -1739,7 +1745,6 @@ static inline int rx_offload(struct t3cdev *tdev, struct sge_rspq *rq,
|
|||
struct sk_buff *skb, struct sk_buff *rx_gather[],
|
||||
unsigned int gather_idx)
|
||||
{
|
||||
rq->offload_pkts++;
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
|
@ -1809,7 +1814,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
|
|||
skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
|
||||
skb->dev->last_rx = jiffies;
|
||||
pi = netdev_priv(skb->dev);
|
||||
if (pi->rx_csum_offload && p->csum_valid && p->csum == 0xffff &&
|
||||
if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) &&
|
||||
!p->fragment) {
|
||||
rspq_to_qset(rq)->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
@ -1956,7 +1961,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
|
|||
int eth, ethpad = 2;
|
||||
struct sk_buff *skb = NULL;
|
||||
u32 len, flags = ntohl(r->flags);
|
||||
u32 rss_hi = *(const u32 *)r, rss_lo = r->rss_hdr.rss_hash_val;
|
||||
__be32 rss_hi = *(const __be32 *)r, rss_lo = r->rss_hdr.rss_hash_val;
|
||||
|
||||
eth = r->rss_hdr.opcode == CPL_RX_PKT;
|
||||
|
||||
|
@ -2033,6 +2038,7 @@ no_mem:
|
|||
if (eth)
|
||||
rx_eth(adap, q, skb, ethpad);
|
||||
else {
|
||||
q->offload_pkts++;
|
||||
/* Preserve the RSS info in csum & priority */
|
||||
skb->csum = rss_hi;
|
||||
skb->priority = rss_lo;
|
||||
|
@ -2442,6 +2448,15 @@ irq_handler_t t3_intr_handler(struct adapter *adap, int polling)
|
|||
return t3_intr;
|
||||
}
|
||||
|
||||
#define SGE_PARERR (F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \
|
||||
F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
|
||||
V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
|
||||
F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
|
||||
F_HIRCQPARITYERROR)
|
||||
#define SGE_FRAMINGERR (F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR)
|
||||
#define SGE_FATALERR (SGE_PARERR | SGE_FRAMINGERR | F_RSPQCREDITOVERFOW | \
|
||||
F_RSPQDISABLED)
|
||||
|
||||
/**
|
||||
* t3_sge_err_intr_handler - SGE async event interrupt handler
|
||||
* @adapter: the adapter
|
||||
|
@ -2452,6 +2467,13 @@ void t3_sge_err_intr_handler(struct adapter *adapter)
|
|||
{
|
||||
unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE);
|
||||
|
||||
if (status & SGE_PARERR)
|
||||
CH_ALERT(adapter, "SGE parity error (0x%x)\n",
|
||||
status & SGE_PARERR);
|
||||
if (status & SGE_FRAMINGERR)
|
||||
CH_ALERT(adapter, "SGE framing error (0x%x)\n",
|
||||
status & SGE_FRAMINGERR);
|
||||
|
||||
if (status & F_RSPQCREDITOVERFOW)
|
||||
CH_ALERT(adapter, "SGE response queue credit overflow\n");
|
||||
|
||||
|
@ -2468,7 +2490,7 @@ void t3_sge_err_intr_handler(struct adapter *adapter)
|
|||
status & F_HIPIODRBDROPERR ? "high" : "lo");
|
||||
|
||||
t3_write_reg(adapter, A_SG_INT_CAUSE, status);
|
||||
if (status & (F_RSPQCREDITOVERFOW | F_RSPQDISABLED))
|
||||
if (status & SGE_FATALERR)
|
||||
t3_fatal_err(adapter);
|
||||
}
|
||||
|
||||
|
@ -2780,7 +2802,7 @@ void t3_sge_init(struct adapter *adap, struct sge_params *p)
|
|||
unsigned int ctrl, ups = ffs(pci_resource_len(adap->pdev, 2) >> 12);
|
||||
|
||||
ctrl = F_DROPPKT | V_PKTSHIFT(2) | F_FLMODE | F_AVOIDCQOVFL |
|
||||
F_CQCRDTCTRL |
|
||||
F_CQCRDTCTRL | F_CONGMODE | F_TNLFLMODE | F_FATLPERREN |
|
||||
V_HOSTPAGESIZE(PAGE_SHIFT - 11) | F_BIGENDIANINGRESS |
|
||||
V_USERSPACESIZE(ups ? ups - 1 : 0) | F_ISCSICOALESCING;
|
||||
#if SGE_NUM_GENBITS == 1
|
||||
|
@ -2789,7 +2811,6 @@ void t3_sge_init(struct adapter *adap, struct sge_params *p)
|
|||
if (adap->params.rev > 0) {
|
||||
if (!(adap->flags & (USING_MSIX | USING_MSI)))
|
||||
ctrl |= F_ONEINTMULTQ | F_OPTONEINTMULTQ;
|
||||
ctrl |= F_CQCRDTCTRL | F_AVOIDCQOVFL;
|
||||
}
|
||||
t3_write_reg(adap, A_SG_CONTROL, ctrl);
|
||||
t3_write_reg(adap, A_SG_EGR_RCQ_DRB_THRSH, V_HIRCQDRBTHRSH(512) |
|
||||
|
@ -2797,7 +2818,8 @@ void t3_sge_init(struct adapter *adap, struct sge_params *p)
|
|||
t3_write_reg(adap, A_SG_TIMER_TICK, core_ticks_per_usec(adap) / 10);
|
||||
t3_write_reg(adap, A_SG_CMDQ_CREDIT_TH, V_THRESHOLD(32) |
|
||||
V_TIMEOUT(200 * core_ticks_per_usec(adap)));
|
||||
t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH, 1000);
|
||||
t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH,
|
||||
adap->params.rev < T3_REV_C ? 1000 : 500);
|
||||
t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256);
|
||||
t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000);
|
||||
t3_write_reg(adap, A_SG_LO_DRB_LO_THRSH, 256);
|
||||
|
|
|
@ -62,7 +62,7 @@ int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
|
|||
return 0;
|
||||
}
|
||||
if (--attempts == 0)
|
||||
return -EAGAIN;
|
||||
return -EAGAIN;
|
||||
if (delay)
|
||||
udelay(delay);
|
||||
}
|
||||
|
@ -537,10 +537,11 @@ struct t3_vpd {
|
|||
* addres is written to the control register. The hardware device will
|
||||
* set the flag to 1 when 4 bytes have been read into the data register.
|
||||
*/
|
||||
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
|
||||
int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data)
|
||||
{
|
||||
u16 val;
|
||||
int attempts = EEPROM_MAX_POLL;
|
||||
u32 v;
|
||||
unsigned int base = adapter->params.pci.vpd_cap_addr;
|
||||
|
||||
if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3))
|
||||
|
@ -556,8 +557,8 @@ int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
|
|||
CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr);
|
||||
return -EIO;
|
||||
}
|
||||
pci_read_config_dword(adapter->pdev, base + PCI_VPD_DATA, data);
|
||||
*data = le32_to_cpu(*data);
|
||||
pci_read_config_dword(adapter->pdev, base + PCI_VPD_DATA, &v);
|
||||
*data = cpu_to_le32(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -570,7 +571,7 @@ int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
|
|||
* Write a 32-bit word to a location in VPD EEPROM using the card's PCI
|
||||
* VPD ROM capability.
|
||||
*/
|
||||
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data)
|
||||
int t3_seeprom_write(struct adapter *adapter, u32 addr, __le32 data)
|
||||
{
|
||||
u16 val;
|
||||
int attempts = EEPROM_MAX_POLL;
|
||||
|
@ -580,7 +581,7 @@ int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data)
|
|||
return -EINVAL;
|
||||
|
||||
pci_write_config_dword(adapter->pdev, base + PCI_VPD_DATA,
|
||||
cpu_to_le32(data));
|
||||
le32_to_cpu(data));
|
||||
pci_write_config_word(adapter->pdev,base + PCI_VPD_ADDR,
|
||||
addr | PCI_VPD_ADDR_F);
|
||||
do {
|
||||
|
@ -631,14 +632,14 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
|
|||
* Card information is normally at VPD_BASE but some early cards had
|
||||
* it at 0.
|
||||
*/
|
||||
ret = t3_seeprom_read(adapter, VPD_BASE, (u32 *)&vpd);
|
||||
ret = t3_seeprom_read(adapter, VPD_BASE, (__le32 *)&vpd);
|
||||
if (ret)
|
||||
return ret;
|
||||
addr = vpd.id_tag == 0x82 ? VPD_BASE : 0;
|
||||
|
||||
for (i = 0; i < sizeof(vpd); i += 4) {
|
||||
ret = t3_seeprom_read(adapter, addr + i,
|
||||
(u32 *)((u8 *)&vpd + i));
|
||||
(__le32 *)((u8 *)&vpd + i));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -865,7 +866,7 @@ int t3_get_tp_version(struct adapter *adapter, u32 *vers)
|
|||
1, 1, 5, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
*vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
|
||||
|
||||
return 0;
|
||||
|
@ -896,7 +897,7 @@ int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
|
|||
major = G_TP_VERSION_MAJOR(vers);
|
||||
minor = G_TP_VERSION_MINOR(vers);
|
||||
|
||||
if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
|
||||
if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
|
||||
return 0;
|
||||
|
||||
if (major != TP_VERSION_MAJOR)
|
||||
|
@ -913,7 +914,7 @@ int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
|
|||
}
|
||||
|
||||
/**
|
||||
* t3_check_tpsram - check if provided protocol SRAM
|
||||
* t3_check_tpsram - check if provided protocol SRAM
|
||||
* is compatible with this driver
|
||||
* @adapter: the adapter
|
||||
* @tp_sram: the firmware image to write
|
||||
|
@ -926,7 +927,7 @@ int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
|
|||
{
|
||||
u32 csum;
|
||||
unsigned int i;
|
||||
const u32 *p = (const u32 *)tp_sram;
|
||||
const __be32 *p = (const __be32 *)tp_sram;
|
||||
|
||||
/* Verify checksum */
|
||||
for (csum = 0, i = 0; i < size / sizeof(csum); i++)
|
||||
|
@ -988,13 +989,17 @@ int t3_check_fw_version(struct adapter *adapter, int *must_load)
|
|||
CH_ERR(adapter, "found wrong FW version(%u.%u), "
|
||||
"driver needs version %u.%u\n", major, minor,
|
||||
FW_VERSION_MAJOR, FW_VERSION_MINOR);
|
||||
else {
|
||||
else if (minor < FW_VERSION_MINOR) {
|
||||
*must_load = 0;
|
||||
CH_WARN(adapter, "found wrong FW minor version(%u.%u), "
|
||||
CH_WARN(adapter, "found old FW minor version(%u.%u), "
|
||||
"driver compiled for version %u.%u\n", major, minor,
|
||||
FW_VERSION_MAJOR, FW_VERSION_MINOR);
|
||||
} else {
|
||||
CH_WARN(adapter, "found newer FW version(%u.%u), "
|
||||
"driver compiled for version %u.%u\n", major, minor,
|
||||
FW_VERSION_MAJOR, FW_VERSION_MINOR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1036,7 +1041,7 @@ int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size)
|
|||
{
|
||||
u32 csum;
|
||||
unsigned int i;
|
||||
const u32 *p = (const u32 *)fw_data;
|
||||
const __be32 *p = (const __be32 *)fw_data;
|
||||
int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
|
||||
|
||||
if ((size & 3) || size < FW_MIN_SIZE)
|
||||
|
@ -1259,7 +1264,13 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
|
|||
return fatal;
|
||||
}
|
||||
|
||||
#define SGE_INTR_MASK (F_RSPQDISABLED)
|
||||
#define SGE_INTR_MASK (F_RSPQDISABLED | \
|
||||
F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR | \
|
||||
F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \
|
||||
F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
|
||||
V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
|
||||
F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
|
||||
F_HIRCQPARITYERROR)
|
||||
#define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
|
||||
F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
|
||||
F_NFASRCHFAIL)
|
||||
|
@ -1276,16 +1287,23 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
|
|||
#define PCIE_INTR_MASK (F_UNXSPLCPLERRR | F_UNXSPLCPLERRC | F_PCIE_PIOPARERR |\
|
||||
F_PCIE_WFPARERR | F_PCIE_RFPARERR | F_PCIE_CFPARERR | \
|
||||
/* V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR) | */ \
|
||||
V_BISTERR(M_BISTERR) | F_PEXERR)
|
||||
#define ULPRX_INTR_MASK F_PARERR
|
||||
#define ULPTX_INTR_MASK 0
|
||||
#define CPLSW_INTR_MASK (F_TP_FRAMING_ERROR | \
|
||||
F_RETRYBUFPARERR | F_RETRYLUTPARERR | F_RXPARERR | \
|
||||
F_TXPARERR | V_BISTERR(M_BISTERR))
|
||||
#define ULPRX_INTR_MASK (F_PARERRDATA | F_PARERRPCMD | F_ARBPF1PERR | \
|
||||
F_ARBPF0PERR | F_ARBFPERR | F_PCMDMUXPERR | \
|
||||
F_DATASELFRAMEERR1 | F_DATASELFRAMEERR0)
|
||||
#define ULPTX_INTR_MASK 0xfc
|
||||
#define CPLSW_INTR_MASK (F_CIM_OP_MAP_PERR | F_TP_FRAMING_ERROR | \
|
||||
F_SGE_FRAMING_ERROR | F_CIM_FRAMING_ERROR | \
|
||||
F_ZERO_SWITCH_ERROR)
|
||||
#define CIM_INTR_MASK (F_BLKWRPLINT | F_BLKRDPLINT | F_BLKWRCTLINT | \
|
||||
F_BLKRDCTLINT | F_BLKWRFLASHINT | F_BLKRDFLASHINT | \
|
||||
F_SGLWRFLASHINT | F_WRBLKFLASHINT | F_BLKWRBOOTINT | \
|
||||
F_FLASHRANGEINT | F_SDRAMRANGEINT | F_RSVDSPACEINT)
|
||||
F_FLASHRANGEINT | F_SDRAMRANGEINT | F_RSVDSPACEINT | \
|
||||
F_DRAMPARERR | F_ICACHEPARERR | F_DCACHEPARERR | \
|
||||
F_OBQSGEPARERR | F_OBQULPHIPARERR | F_OBQULPLOPARERR | \
|
||||
F_IBQSGELOPARERR | F_IBQSGEHIPARERR | F_IBQULPPARERR | \
|
||||
F_IBQTPPARERR | F_ITAGPARERR | F_DTAGPARERR)
|
||||
#define PMTX_INTR_MASK (F_ZERO_C_CMD_ERROR | ICSPI_FRM_ERR | OESPI_FRM_ERR | \
|
||||
V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR) | \
|
||||
V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR))
|
||||
|
@ -1354,6 +1372,10 @@ static void pcie_intr_handler(struct adapter *adapter)
|
|||
{F_PCIE_CFPARERR, "PCI command FIFO parity error", -1, 1},
|
||||
{V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR),
|
||||
"PCI MSI-X table/PBA parity error", -1, 1},
|
||||
{F_RETRYBUFPARERR, "PCI retry buffer parity error", -1, 1},
|
||||
{F_RETRYLUTPARERR, "PCI retry LUT parity error", -1, 1},
|
||||
{F_RXPARERR, "PCI Rx parity error", -1, 1},
|
||||
{F_TXPARERR, "PCI Tx parity error", -1, 1},
|
||||
{V_BISTERR(M_BISTERR), "PCI BIST error", -1, 1},
|
||||
{0}
|
||||
};
|
||||
|
@ -1379,8 +1401,16 @@ static void tp_intr_handler(struct adapter *adapter)
|
|||
{0}
|
||||
};
|
||||
|
||||
static struct intr_info tp_intr_info_t3c[] = {
|
||||
{0x1fffffff, "TP parity error", -1, 1},
|
||||
{F_FLMRXFLSTEMPTY, "TP out of Rx pages", -1, 1},
|
||||
{F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
if (t3_handle_intr_status(adapter, A_TP_INT_CAUSE, 0xffffffff,
|
||||
tp_intr_info, NULL))
|
||||
adapter->params.rev < T3_REV_C ?
|
||||
tp_intr_info : tp_intr_info_t3c, NULL))
|
||||
t3_fatal_err(adapter);
|
||||
}
|
||||
|
||||
|
@ -1402,6 +1432,18 @@ static void cim_intr_handler(struct adapter *adapter)
|
|||
{F_BLKWRCTLINT, "CIM block write to CTL space", -1, 1},
|
||||
{F_BLKRDPLINT, "CIM block read from PL space", -1, 1},
|
||||
{F_BLKWRPLINT, "CIM block write to PL space", -1, 1},
|
||||
{F_DRAMPARERR, "CIM DRAM parity error", -1, 1},
|
||||
{F_ICACHEPARERR, "CIM icache parity error", -1, 1},
|
||||
{F_DCACHEPARERR, "CIM dcache parity error", -1, 1},
|
||||
{F_OBQSGEPARERR, "CIM OBQ SGE parity error", -1, 1},
|
||||
{F_OBQULPHIPARERR, "CIM OBQ ULPHI parity error", -1, 1},
|
||||
{F_OBQULPLOPARERR, "CIM OBQ ULPLO parity error", -1, 1},
|
||||
{F_IBQSGELOPARERR, "CIM IBQ SGELO parity error", -1, 1},
|
||||
{F_IBQSGEHIPARERR, "CIM IBQ SGEHI parity error", -1, 1},
|
||||
{F_IBQULPPARERR, "CIM IBQ ULP parity error", -1, 1},
|
||||
{F_IBQTPPARERR, "CIM IBQ TP parity error", -1, 1},
|
||||
{F_ITAGPARERR, "CIM itag parity error", -1, 1},
|
||||
{F_DTAGPARERR, "CIM dtag parity error", -1, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -1416,7 +1458,14 @@ static void cim_intr_handler(struct adapter *adapter)
|
|||
static void ulprx_intr_handler(struct adapter *adapter)
|
||||
{
|
||||
static const struct intr_info ulprx_intr_info[] = {
|
||||
{F_PARERR, "ULP RX parity error", -1, 1},
|
||||
{F_PARERRDATA, "ULP RX data parity error", -1, 1},
|
||||
{F_PARERRPCMD, "ULP RX command parity error", -1, 1},
|
||||
{F_ARBPF1PERR, "ULP RX ArbPF1 parity error", -1, 1},
|
||||
{F_ARBPF0PERR, "ULP RX ArbPF0 parity error", -1, 1},
|
||||
{F_ARBFPERR, "ULP RX ArbF parity error", -1, 1},
|
||||
{F_PCMDMUXPERR, "ULP RX PCMDMUX parity error", -1, 1},
|
||||
{F_DATASELFRAMEERR1, "ULP RX frame error", -1, 1},
|
||||
{F_DATASELFRAMEERR0, "ULP RX frame error", -1, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -1435,6 +1484,7 @@ static void ulptx_intr_handler(struct adapter *adapter)
|
|||
STAT_ULP_CH0_PBL_OOB, 0},
|
||||
{F_PBL_BOUND_ERR_CH1, "ULP TX channel 1 PBL out of bounds",
|
||||
STAT_ULP_CH1_PBL_OOB, 0},
|
||||
{0xfc, "ULP TX parity error", -1, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -1509,7 +1559,8 @@ static void pmrx_intr_handler(struct adapter *adapter)
|
|||
static void cplsw_intr_handler(struct adapter *adapter)
|
||||
{
|
||||
static const struct intr_info cplsw_intr_info[] = {
|
||||
/* { F_CIM_OVFL_ERROR, "CPL switch CIM overflow", -1, 1 }, */
|
||||
{F_CIM_OP_MAP_PERR, "CPL switch CIM parity error", -1, 1},
|
||||
{F_CIM_OVFL_ERROR, "CPL switch CIM overflow", -1, 1},
|
||||
{F_TP_FRAMING_ERROR, "CPL switch TP framing error", -1, 1},
|
||||
{F_SGE_FRAMING_ERROR, "CPL switch SGE framing error", -1, 1},
|
||||
{F_CIM_FRAMING_ERROR, "CPL switch CIM framing error", -1, 1},
|
||||
|
@ -1730,7 +1781,6 @@ void t3_intr_enable(struct adapter *adapter)
|
|||
MC7_INTR_MASK},
|
||||
{A_MC5_DB_INT_ENABLE, MC5_INTR_MASK},
|
||||
{A_ULPRX_INT_ENABLE, ULPRX_INTR_MASK},
|
||||
{A_TP_INT_ENABLE, 0x3bfffff},
|
||||
{A_PM1_TX_INT_ENABLE, PMTX_INTR_MASK},
|
||||
{A_PM1_RX_INT_ENABLE, PMRX_INTR_MASK},
|
||||
{A_CIM_HOST_INT_ENABLE, CIM_INTR_MASK},
|
||||
|
@ -1740,6 +1790,8 @@ void t3_intr_enable(struct adapter *adapter)
|
|||
adapter->slow_intr_mask = PL_INTR_MASK;
|
||||
|
||||
t3_write_regs(adapter, intr_en_avp, ARRAY_SIZE(intr_en_avp), 0);
|
||||
t3_write_reg(adapter, A_TP_INT_ENABLE,
|
||||
adapter->params.rev >= T3_REV_C ? 0x2bfffff : 0x3bfffff);
|
||||
|
||||
if (adapter->params.rev > 0) {
|
||||
t3_write_reg(adapter, A_CPL_INTR_ENABLE,
|
||||
|
@ -1894,6 +1946,16 @@ static int t3_sge_write_context(struct adapter *adapter, unsigned int id,
|
|||
0, SG_CONTEXT_CMD_ATTEMPTS, 1);
|
||||
}
|
||||
|
||||
static int clear_sge_ctxt(struct adapter *adap, unsigned int id,
|
||||
unsigned int type)
|
||||
{
|
||||
t3_write_reg(adap, A_SG_CONTEXT_DATA0, 0);
|
||||
t3_write_reg(adap, A_SG_CONTEXT_DATA1, 0);
|
||||
t3_write_reg(adap, A_SG_CONTEXT_DATA2, 0);
|
||||
t3_write_reg(adap, A_SG_CONTEXT_DATA3, 0);
|
||||
return t3_sge_write_context(adap, id, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_sge_init_ecntxt - initialize an SGE egress context
|
||||
* @adapter: the adapter to configure
|
||||
|
@ -2395,7 +2457,7 @@ static inline unsigned int pm_num_pages(unsigned int mem_size,
|
|||
t3_write_reg((adap), A_ ## reg, (start)); \
|
||||
start += size
|
||||
|
||||
/*
|
||||
/**
|
||||
* partition_mem - partition memory and configure TP memory settings
|
||||
* @adap: the adapter
|
||||
* @p: the TP parameters
|
||||
|
@ -2480,7 +2542,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
|
|||
V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
|
||||
V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
|
||||
F_AUTOCAREFUL | F_AUTOENABLE | V_DACK_MODE(1));
|
||||
t3_set_reg_field(adap, A_TP_IN_CONFIG, F_IPV6ENABLE | F_NICMODE,
|
||||
t3_set_reg_field(adap, A_TP_IN_CONFIG, F_RXFBARBPRIO | F_TXFBARBPRIO,
|
||||
F_IPV6ENABLE | F_NICMODE);
|
||||
t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
|
||||
t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
|
||||
|
@ -2492,10 +2554,12 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
|
|||
F_ENABLEEPCMDAFULL,
|
||||
F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
|
||||
F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
|
||||
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
|
||||
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL,
|
||||
F_ENABLEIPV6RSS | F_ENABLENONOFDTNLSYN |
|
||||
F_ENABLEARPMISS | F_DISBLEDAPARBIT0);
|
||||
t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
|
||||
t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
|
||||
|
||||
|
||||
if (adap->params.rev > 0) {
|
||||
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
|
||||
t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
|
||||
|
@ -2505,6 +2569,11 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
|
|||
} else
|
||||
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
|
||||
|
||||
if (adap->params.rev == T3_REV_C)
|
||||
t3_set_reg_field(adap, A_TP_PC_CONFIG,
|
||||
V_TABLELATENCYDELTA(M_TABLELATENCYDELTA),
|
||||
V_TABLELATENCYDELTA(4));
|
||||
|
||||
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
|
||||
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
|
||||
t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
|
||||
|
@ -2809,15 +2878,15 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
|
|||
int t3_set_proto_sram(struct adapter *adap, u8 *data)
|
||||
{
|
||||
int i;
|
||||
u32 *buf = (u32 *)data;
|
||||
__be32 *buf = (__be32 *)data;
|
||||
|
||||
for (i = 0; i < PROTO_SRAM_LINES; i++) {
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
|
||||
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, be32_to_cpu(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, be32_to_cpu(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, be32_to_cpu(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, be32_to_cpu(*buf++));
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, be32_to_cpu(*buf++));
|
||||
|
||||
t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
|
||||
if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
|
||||
return -EIO;
|
||||
|
@ -3194,7 +3263,8 @@ static void config_pcie(struct adapter *adap)
|
|||
V_REPLAYLMT(rpllmt));
|
||||
|
||||
t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff);
|
||||
t3_set_reg_field(adap, A_PCIE_CFG, F_PCIE_CLIDECEN, F_PCIE_CLIDECEN);
|
||||
t3_set_reg_field(adap, A_PCIE_CFG, 0,
|
||||
F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3207,7 +3277,7 @@ static void config_pcie(struct adapter *adap)
|
|||
*/
|
||||
int t3_init_hw(struct adapter *adapter, u32 fw_params)
|
||||
{
|
||||
int err = -EIO, attempts = 100;
|
||||
int err = -EIO, attempts, i;
|
||||
const struct vpd_params *vpd = &adapter->params.vpd;
|
||||
|
||||
if (adapter->params.rev > 0)
|
||||
|
@ -3225,6 +3295,10 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
|
|||
adapter->params.mc5.nfilters,
|
||||
adapter->params.mc5.nroutes))
|
||||
goto out_err;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
if (clear_sge_ctxt(adapter, i, F_CQ))
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (tp_init(adapter, &adapter->params.tp))
|
||||
|
@ -3240,7 +3314,12 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
|
|||
if (is_pcie(adapter))
|
||||
config_pcie(adapter);
|
||||
else
|
||||
t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
|
||||
t3_set_reg_field(adapter, A_PCIX_CFG, 0,
|
||||
F_DMASTOPEN | F_CLIDECEN);
|
||||
|
||||
if (adapter->params.rev == T3_REV_C)
|
||||
t3_set_reg_field(adapter, A_ULPTX_CONFIG, 0,
|
||||
F_CFG_CQE_SOP_MASK);
|
||||
|
||||
t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
|
||||
t3_write_reg(adapter, A_PM1_RX_MODE, 0);
|
||||
|
@ -3253,6 +3332,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
|
|||
V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2));
|
||||
t3_read_reg(adapter, A_CIM_BOOT_CFG); /* flush */
|
||||
|
||||
attempts = 100;
|
||||
do { /* wait for uP to initialize */
|
||||
msleep(20);
|
||||
} while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
|
||||
|
@ -3387,6 +3467,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
|
|||
t3_write_reg(adapter, A_T3DBG_GPIO_EN,
|
||||
ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
|
||||
t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
|
||||
t3_write_reg(adapter, A_SG_OCO_BASE, V_BASE1(0xfff));
|
||||
|
||||
if (adapter->params.rev == 0 || !uses_xaui(adapter))
|
||||
val |= F_ENRGMII;
|
||||
|
@ -3403,13 +3484,13 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
|
|||
}
|
||||
|
||||
/*
|
||||
* Reset the adapter.
|
||||
* Reset the adapter.
|
||||
* Older PCIe cards lose their config space during reset, PCI-X
|
||||
* ones don't.
|
||||
*/
|
||||
static int t3_reset_adapter(struct adapter *adapter)
|
||||
{
|
||||
int i, save_and_restore_pcie =
|
||||
int i, save_and_restore_pcie =
|
||||
adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
|
||||
uint16_t devid = 0;
|
||||
|
||||
|
@ -3436,6 +3517,36 @@ static int t3_reset_adapter(struct adapter *adapter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit init_parity(struct adapter *adap)
|
||||
{
|
||||
int i, err, addr;
|
||||
|
||||
if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
|
||||
return -EBUSY;
|
||||
|
||||
for (err = i = 0; !err && i < 16; i++)
|
||||
err = clear_sge_ctxt(adap, i, F_EGRESS);
|
||||
for (i = 0xfff0; !err && i <= 0xffff; i++)
|
||||
err = clear_sge_ctxt(adap, i, F_EGRESS);
|
||||
for (i = 0; !err && i < SGE_QSETS; i++)
|
||||
err = clear_sge_ctxt(adap, i, F_RESPONSEQ);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
t3_write_reg(adap, A_CIM_IBQ_DBG_DATA, 0);
|
||||
for (i = 0; i < 4; i++)
|
||||
for (addr = 0; addr <= M_IBQDBGADDR; addr++) {
|
||||
t3_write_reg(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGEN |
|
||||
F_IBQDBGWR | V_IBQDBGQID(i) |
|
||||
V_IBQDBGADDR(addr));
|
||||
err = t3_wait_op_done(adap, A_CIM_IBQ_DBG_CFG,
|
||||
F_IBQDBGBUSY, 0, 2, 1);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize adapter SW state for the various HW modules, set initial values
|
||||
* for some adapter tunables, take PHYs out of reset, and initialize the MDIO
|
||||
|
@ -3503,6 +3614,9 @@ int __devinit t3_prep_adapter(struct adapter *adapter,
|
|||
}
|
||||
|
||||
early_hw_init(adapter, ai);
|
||||
ret = init_parity(adapter);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_port(adapter, i) {
|
||||
u8 hw_addr[6];
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define DRV_VERSION "1.0-ko"
|
||||
|
||||
/* Firmware version */
|
||||
#define FW_VERSION_MAJOR 4
|
||||
#define FW_VERSION_MINOR 6
|
||||
#define FW_VERSION_MAJOR 5
|
||||
#define FW_VERSION_MINOR 0
|
||||
#define FW_VERSION_MICRO 0
|
||||
#endif /* __CHELSIO_VERSION_H */
|
||||
|
|
|
@ -153,7 +153,7 @@ static int t3b2_mac_reset(struct cmac *mac)
|
|||
unsigned int oft = mac->offset;
|
||||
u32 val;
|
||||
|
||||
if (!macidx(mac))
|
||||
if (!macidx(mac))
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
|
||||
else
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
|
||||
|
@ -187,11 +187,11 @@ static int t3b2_mac_reset(struct cmac *mac)
|
|||
msleep(1);
|
||||
t3b_pcs_reset(mac);
|
||||
}
|
||||
t3_write_reg(adap, A_XGM_RX_CFG + oft,
|
||||
t3_write_reg(adap, A_XGM_RX_CFG + oft,
|
||||
F_DISPAUSEFRAMES | F_EN1536BFRAMES |
|
||||
F_RMFCS | F_ENJUMBO | F_ENHASHMCAST);
|
||||
|
||||
if (!macidx(mac))
|
||||
if (!macidx(mac))
|
||||
t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
|
||||
else
|
||||
t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
|
||||
|
@ -336,7 +336,7 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
|
|||
* Adjust the PAUSE frame watermarks. We always set the LWM, and the
|
||||
* HWM only if flow-control is enabled.
|
||||
*/
|
||||
hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu,
|
||||
hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu,
|
||||
MAC_RXFIFO_SIZE * 38 / 100);
|
||||
hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
|
||||
lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
|
||||
|
@ -449,7 +449,7 @@ int t3_mac_enable(struct cmac *mac, int which)
|
|||
struct adapter *adap = mac->adapter;
|
||||
unsigned int oft = mac->offset;
|
||||
struct mac_stats *s = &mac->stats;
|
||||
|
||||
|
||||
if (which & MAC_DIRECTION_TX) {
|
||||
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
|
||||
t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401);
|
||||
|
|
|
@ -719,15 +719,15 @@ out:
|
|||
spin_unlock(&lp->lock);
|
||||
}
|
||||
|
||||
static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id)
|
||||
static irqreturn_t lance_dma_merr_int(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
|
||||
printk("%s: DMA error\n", dev->name);
|
||||
printk(KERN_ERR "%s: DMA error\n", dev->name);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t lance_interrupt(const int irq, void *dev_id)
|
||||
static irqreturn_t lance_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
struct lance_private *lp = netdev_priv(dev);
|
||||
|
|
|
@ -106,6 +106,13 @@
|
|||
* the RFD, the RFD must be dma_sync'ed to maintain a consistent
|
||||
* view from software and hardware.
|
||||
*
|
||||
* In order to keep updates to the RFD link field from colliding with
|
||||
* hardware writes to mark packets complete, we use the feature that
|
||||
* hardware will not write to a size 0 descriptor and mark the previous
|
||||
* packet as end-of-list (EL). After updating the link, we remove EL
|
||||
* and only then restore the size such that hardware may use the
|
||||
* previous-to-end RFD.
|
||||
*
|
||||
* Under typical operation, the receive unit (RU) is start once,
|
||||
* and the controller happily fills RFDs as frames arrive. If
|
||||
* replacement RFDs cannot be allocated, or the RU goes non-active,
|
||||
|
@ -281,6 +288,7 @@ struct csr {
|
|||
};
|
||||
|
||||
enum scb_status {
|
||||
rus_no_res = 0x08,
|
||||
rus_ready = 0x10,
|
||||
rus_mask = 0x3C,
|
||||
};
|
||||
|
@ -393,12 +401,12 @@ enum cb_command {
|
|||
};
|
||||
|
||||
struct rfd {
|
||||
u16 status;
|
||||
u16 command;
|
||||
u32 link;
|
||||
u32 rbd;
|
||||
u16 actual_size;
|
||||
u16 size;
|
||||
__le16 status;
|
||||
__le16 command;
|
||||
__le32 link;
|
||||
__le32 rbd;
|
||||
__le16 actual_size;
|
||||
__le16 size;
|
||||
};
|
||||
|
||||
struct rx {
|
||||
|
@ -453,19 +461,19 @@ struct config {
|
|||
|
||||
#define E100_MAX_MULTICAST_ADDRS 64
|
||||
struct multi {
|
||||
u16 count;
|
||||
__le16 count;
|
||||
u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/];
|
||||
};
|
||||
|
||||
/* Important: keep total struct u32-aligned */
|
||||
#define UCODE_SIZE 134
|
||||
struct cb {
|
||||
u16 status;
|
||||
u16 command;
|
||||
u32 link;
|
||||
__le16 status;
|
||||
__le16 command;
|
||||
__le32 link;
|
||||
union {
|
||||
u8 iaaddr[ETH_ALEN];
|
||||
u32 ucode[UCODE_SIZE];
|
||||
__le32 ucode[UCODE_SIZE];
|
||||
struct config config;
|
||||
struct multi multi;
|
||||
struct {
|
||||
|
@ -474,12 +482,12 @@ struct cb {
|
|||
u8 threshold;
|
||||
u8 tbd_count;
|
||||
struct {
|
||||
u32 buf_addr;
|
||||
u16 size;
|
||||
__le32 buf_addr;
|
||||
__le16 size;
|
||||
u16 eol;
|
||||
} tbd;
|
||||
} tcb;
|
||||
u32 dump_buffer_addr;
|
||||
__le32 dump_buffer_addr;
|
||||
} u;
|
||||
struct cb *next, *prev;
|
||||
dma_addr_t dma_addr;
|
||||
|
@ -491,15 +499,15 @@ enum loopback {
|
|||
};
|
||||
|
||||
struct stats {
|
||||
u32 tx_good_frames, tx_max_collisions, tx_late_collisions,
|
||||
__le32 tx_good_frames, tx_max_collisions, tx_late_collisions,
|
||||
tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
|
||||
tx_multiple_collisions, tx_total_collisions;
|
||||
u32 rx_good_frames, rx_crc_errors, rx_alignment_errors,
|
||||
__le32 rx_good_frames, rx_crc_errors, rx_alignment_errors,
|
||||
rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
|
||||
rx_short_frame_errors;
|
||||
u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
|
||||
u16 xmt_tco_frames, rcv_tco_frames;
|
||||
u32 complete;
|
||||
__le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
|
||||
__le16 xmt_tco_frames, rcv_tco_frames;
|
||||
__le32 complete;
|
||||
};
|
||||
|
||||
struct mem {
|
||||
|
@ -544,7 +552,7 @@ struct nic {
|
|||
struct cb *cb_to_use;
|
||||
struct cb *cb_to_send;
|
||||
struct cb *cb_to_clean;
|
||||
u16 tx_command;
|
||||
__le16 tx_command;
|
||||
/* End: frequently used values: keep adjacent for cache effect */
|
||||
|
||||
enum {
|
||||
|
@ -585,7 +593,7 @@ struct nic {
|
|||
|
||||
u16 leds;
|
||||
u16 eeprom_wc;
|
||||
u16 eeprom[256];
|
||||
__le16 eeprom[256];
|
||||
spinlock_t mdio_lock;
|
||||
};
|
||||
|
||||
|
@ -663,7 +671,7 @@ static int e100_self_test(struct nic *nic)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data)
|
||||
static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data)
|
||||
{
|
||||
u32 cmd_addr_data[3];
|
||||
u8 ctrl;
|
||||
|
@ -672,7 +680,7 @@ static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data)
|
|||
/* Three cmds: write/erase enable, write data, write/erase disable */
|
||||
cmd_addr_data[0] = op_ewen << (addr_len - 2);
|
||||
cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) |
|
||||
cpu_to_le16(data);
|
||||
le16_to_cpu(data);
|
||||
cmd_addr_data[2] = op_ewds << (addr_len - 2);
|
||||
|
||||
/* Bit-bang cmds to write word to eeprom */
|
||||
|
@ -701,7 +709,7 @@ static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data)
|
|||
};
|
||||
|
||||
/* General technique stolen from the eepro100 driver - very clever */
|
||||
static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
|
||||
static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
|
||||
{
|
||||
u32 cmd_addr_data;
|
||||
u16 data = 0;
|
||||
|
@ -738,7 +746,7 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
|
|||
iowrite8(0, &nic->csr->eeprom_ctrl_lo);
|
||||
e100_write_flush(nic); udelay(4);
|
||||
|
||||
return le16_to_cpu(data);
|
||||
return cpu_to_le16(data);
|
||||
};
|
||||
|
||||
/* Load entire EEPROM image into driver cache and validate checksum */
|
||||
|
@ -753,13 +761,12 @@ static int e100_eeprom_load(struct nic *nic)
|
|||
for(addr = 0; addr < nic->eeprom_wc; addr++) {
|
||||
nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
|
||||
if(addr < nic->eeprom_wc - 1)
|
||||
checksum += cpu_to_le16(nic->eeprom[addr]);
|
||||
checksum += le16_to_cpu(nic->eeprom[addr]);
|
||||
}
|
||||
|
||||
/* The checksum, stored in the last word, is calculated such that
|
||||
* the sum of words should be 0xBABA */
|
||||
checksum = le16_to_cpu(0xBABA - checksum);
|
||||
if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
|
||||
if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) {
|
||||
DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
|
||||
if (!eeprom_bad_csum_allow)
|
||||
return -EAGAIN;
|
||||
|
@ -786,8 +793,8 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
|
|||
/* The checksum, stored in the last word, is calculated such that
|
||||
* the sum of words should be 0xBABA */
|
||||
for(addr = 0; addr < nic->eeprom_wc - 1; addr++)
|
||||
checksum += cpu_to_le16(nic->eeprom[addr]);
|
||||
nic->eeprom[nic->eeprom_wc - 1] = le16_to_cpu(0xBABA - checksum);
|
||||
checksum += le16_to_cpu(nic->eeprom[addr]);
|
||||
nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
|
||||
e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
|
||||
nic->eeprom[nic->eeprom_wc - 1]);
|
||||
|
||||
|
@ -952,7 +959,7 @@ static void e100_get_defaults(struct nic *nic)
|
|||
((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
|
||||
|
||||
/* Template for a freshly allocated RFD */
|
||||
nic->blank_rfd.command = cpu_to_le16(cb_el);
|
||||
nic->blank_rfd.command = 0;
|
||||
nic->blank_rfd.rbd = 0xFFFFFFFF;
|
||||
nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
|
||||
|
||||
|
@ -1485,15 +1492,15 @@ static void e100_update_stats(struct nic *nic)
|
|||
struct net_device *dev = nic->netdev;
|
||||
struct net_device_stats *ns = &dev->stats;
|
||||
struct stats *s = &nic->mem->stats;
|
||||
u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
|
||||
(nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames :
|
||||
__le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
|
||||
(nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames :
|
||||
&s->complete;
|
||||
|
||||
/* Device's stats reporting may take several microseconds to
|
||||
* complete, so where always waiting for results of the
|
||||
* previous command. */
|
||||
|
||||
if(*complete == le32_to_cpu(cuc_dump_reset_complete)) {
|
||||
if(*complete == cpu_to_le32(cuc_dump_reset_complete)) {
|
||||
*complete = 0;
|
||||
nic->tx_frames = le32_to_cpu(s->tx_good_frames);
|
||||
nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
|
||||
|
@ -1783,7 +1790,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
|
|||
rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
|
||||
RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
if(pci_dma_mapping_error(rx->dma_addr)) {
|
||||
if (pci_dma_mapping_error(rx->dma_addr)) {
|
||||
dev_kfree_skb_any(rx->skb);
|
||||
rx->skb = NULL;
|
||||
rx->dma_addr = 0;
|
||||
|
@ -1791,15 +1798,11 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
|
|||
}
|
||||
|
||||
/* Link the RFD to end of RFA by linking previous RFD to
|
||||
* this one, and clearing EL bit of previous. */
|
||||
if(rx->prev->skb) {
|
||||
* this one. We are safe to touch the previous RFD because
|
||||
* it is protected by the before last buffer's el bit being set */
|
||||
if (rx->prev->skb) {
|
||||
struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
|
||||
put_unaligned(cpu_to_le32(rx->dma_addr),
|
||||
(u32 *)&prev_rfd->link);
|
||||
wmb();
|
||||
prev_rfd->command &= ~cpu_to_le16(cb_el);
|
||||
pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
|
||||
sizeof(struct rfd), PCI_DMA_TODEVICE);
|
||||
put_unaligned(cpu_to_le32(rx->dma_addr), &prev_rfd->link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1824,8 +1827,19 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
|
|||
DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);
|
||||
|
||||
/* If data isn't ready, nothing to indicate */
|
||||
if(unlikely(!(rfd_status & cb_complete)))
|
||||
if (unlikely(!(rfd_status & cb_complete))) {
|
||||
/* If the next buffer has the el bit, but we think the receiver
|
||||
* is still running, check to see if it really stopped while
|
||||
* we had interrupts off.
|
||||
* This allows for a fast restart without re-enabling
|
||||
* interrupts */
|
||||
if ((le16_to_cpu(rfd->command) & cb_el) &&
|
||||
(RU_RUNNING == nic->ru_running))
|
||||
|
||||
if (readb(&nic->csr->scb.status) & rus_no_res)
|
||||
nic->ru_running = RU_SUSPENDED;
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
/* Get actual data size */
|
||||
actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
|
||||
|
@ -1836,9 +1850,18 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
|
|||
pci_unmap_single(nic->pdev, rx->dma_addr,
|
||||
RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
|
||||
|
||||
/* this allows for a fast restart without re-enabling interrupts */
|
||||
if(le16_to_cpu(rfd->command) & cb_el)
|
||||
/* If this buffer has the el bit, but we think the receiver
|
||||
* is still running, check to see if it really stopped while
|
||||
* we had interrupts off.
|
||||
* This allows for a fast restart without re-enabling interrupts.
|
||||
* This can happen when the RU sees the size change but also sees
|
||||
* the el bit set. */
|
||||
if ((le16_to_cpu(rfd->command) & cb_el) &&
|
||||
(RU_RUNNING == nic->ru_running)) {
|
||||
|
||||
if (readb(&nic->csr->scb.status) & rus_no_res)
|
||||
nic->ru_running = RU_SUSPENDED;
|
||||
}
|
||||
|
||||
/* Pull off the RFD and put the actual data (minus eth hdr) */
|
||||
skb_reserve(skb, sizeof(struct rfd));
|
||||
|
@ -1870,31 +1893,30 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
|
|||
unsigned int work_to_do)
|
||||
{
|
||||
struct rx *rx;
|
||||
int restart_required = 0;
|
||||
struct rx *rx_to_start = NULL;
|
||||
|
||||
/* are we already rnr? then pay attention!!! this ensures that
|
||||
* the state machine progression never allows a start with a
|
||||
* partially cleaned list, avoiding a race between hardware
|
||||
* and rx_to_clean when in NAPI mode */
|
||||
if(RU_SUSPENDED == nic->ru_running)
|
||||
restart_required = 1;
|
||||
int restart_required = 0, err = 0;
|
||||
struct rx *old_before_last_rx, *new_before_last_rx;
|
||||
struct rfd *old_before_last_rfd, *new_before_last_rfd;
|
||||
|
||||
/* Indicate newly arrived packets */
|
||||
for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
|
||||
int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
|
||||
if(-EAGAIN == err) {
|
||||
/* hit quota so have more work to do, restart once
|
||||
* cleanup is complete */
|
||||
restart_required = 0;
|
||||
err = e100_rx_indicate(nic, rx, work_done, work_to_do);
|
||||
/* Hit quota or no more to clean */
|
||||
if (-EAGAIN == err || -ENODATA == err)
|
||||
break;
|
||||
} else if(-ENODATA == err)
|
||||
break; /* No more to clean */
|
||||
}
|
||||
|
||||
/* save our starting point as the place we'll restart the receiver */
|
||||
if(restart_required)
|
||||
rx_to_start = nic->rx_to_clean;
|
||||
|
||||
/* On EAGAIN, hit quota so have more work to do, restart once
|
||||
* cleanup is complete.
|
||||
* Else, are we already rnr? then pay attention!!! this ensures that
|
||||
* the state machine progression never allows a start with a
|
||||
* partially cleaned list, avoiding a race between hardware
|
||||
* and rx_to_clean when in NAPI mode */
|
||||
if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running)
|
||||
restart_required = 1;
|
||||
|
||||
old_before_last_rx = nic->rx_to_use->prev->prev;
|
||||
old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;
|
||||
|
||||
/* Alloc new skbs to refill list */
|
||||
for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
|
||||
|
@ -1902,10 +1924,42 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
|
|||
break; /* Better luck next time (see watchdog) */
|
||||
}
|
||||
|
||||
new_before_last_rx = nic->rx_to_use->prev->prev;
|
||||
if (new_before_last_rx != old_before_last_rx) {
|
||||
/* Set the el-bit on the buffer that is before the last buffer.
|
||||
* This lets us update the next pointer on the last buffer
|
||||
* without worrying about hardware touching it.
|
||||
* We set the size to 0 to prevent hardware from touching this
|
||||
* buffer.
|
||||
* When the hardware hits the before last buffer with el-bit
|
||||
* and size of 0, it will RNR interrupt, the RUS will go into
|
||||
* the No Resources state. It will not complete nor write to
|
||||
* this buffer. */
|
||||
new_before_last_rfd =
|
||||
(struct rfd *)new_before_last_rx->skb->data;
|
||||
new_before_last_rfd->size = 0;
|
||||
new_before_last_rfd->command |= cpu_to_le16(cb_el);
|
||||
pci_dma_sync_single_for_device(nic->pdev,
|
||||
new_before_last_rx->dma_addr, sizeof(struct rfd),
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
/* Now that we have a new stopping point, we can clear the old
|
||||
* stopping point. We must sync twice to get the proper
|
||||
* ordering on the hardware side of things. */
|
||||
old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
|
||||
pci_dma_sync_single_for_device(nic->pdev,
|
||||
old_before_last_rx->dma_addr, sizeof(struct rfd),
|
||||
PCI_DMA_TODEVICE);
|
||||
old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
|
||||
pci_dma_sync_single_for_device(nic->pdev,
|
||||
old_before_last_rx->dma_addr, sizeof(struct rfd),
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
if(restart_required) {
|
||||
// ack the rnr?
|
||||
writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
|
||||
e100_start_receiver(nic, rx_to_start);
|
||||
e100_start_receiver(nic, nic->rx_to_clean);
|
||||
if(work_done)
|
||||
(*work_done)++;
|
||||
}
|
||||
|
@ -1937,6 +1991,7 @@ static int e100_rx_alloc_list(struct nic *nic)
|
|||
{
|
||||
struct rx *rx;
|
||||
unsigned int i, count = nic->params.rfds.count;
|
||||
struct rfd *before_last;
|
||||
|
||||
nic->rx_to_use = nic->rx_to_clean = NULL;
|
||||
nic->ru_running = RU_UNINITIALIZED;
|
||||
|
@ -1952,6 +2007,19 @@ static int e100_rx_alloc_list(struct nic *nic)
|
|||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
/* Set the el-bit on the buffer that is before the last buffer.
|
||||
* This lets us update the next pointer on the last buffer without
|
||||
* worrying about hardware touching it.
|
||||
* We set the size to 0 to prevent hardware from touching this buffer.
|
||||
* When the hardware hits the before last buffer with el-bit and size
|
||||
* of 0, it will RNR interrupt, the RU will go into the No Resources
|
||||
* state. It will not complete nor write to this buffer. */
|
||||
rx = nic->rxs->prev->prev;
|
||||
before_last = (struct rfd *)rx->skb->data;
|
||||
before_last->command |= cpu_to_le16(cb_el);
|
||||
before_last->size = 0;
|
||||
pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
|
||||
sizeof(struct rfd), PCI_DMA_TODEVICE);
|
||||
|
||||
nic->rx_to_use = nic->rx_to_clean = nic->rxs;
|
||||
nic->ru_running = RU_SUSPENDED;
|
||||
|
@ -2369,7 +2437,7 @@ static const char e100_gstrings_test[][ETH_GSTRING_LEN] = {
|
|||
"Mac loopback (offline)",
|
||||
"Phy loopback (offline)",
|
||||
};
|
||||
#define E100_TEST_LEN sizeof(e100_gstrings_test) / ETH_GSTRING_LEN
|
||||
#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test)
|
||||
|
||||
static void e100_diag_test(struct net_device *netdev,
|
||||
struct ethtool_test *test, u64 *data)
|
||||
|
@ -2431,7 +2499,7 @@ static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
|
|||
"rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets",
|
||||
};
|
||||
#define E100_NET_STATS_LEN 21
|
||||
#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN
|
||||
#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats)
|
||||
|
||||
static int e100_get_sset_count(struct net_device *netdev, int sset)
|
||||
{
|
||||
|
|
|
@ -110,7 +110,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
|
|||
"Interrupt test (offline)", "Loopback test (offline)",
|
||||
"Link test (on/offline)"
|
||||
};
|
||||
#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
|
||||
#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
|
||||
|
||||
static int
|
||||
e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
|
@ -728,39 +728,65 @@ err_setup:
|
|||
return err;
|
||||
}
|
||||
|
||||
#define REG_PATTERN_TEST(R, M, W) \
|
||||
{ \
|
||||
uint32_t pat, val; \
|
||||
const uint32_t test[] = \
|
||||
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
|
||||
for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \
|
||||
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
|
||||
val = E1000_READ_REG(&adapter->hw, R); \
|
||||
if (val != (test[pat] & W & M)) { \
|
||||
DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
|
||||
"0x%08X expected 0x%08X\n", \
|
||||
E1000_##R, val, (test[pat] & W & M)); \
|
||||
*data = (adapter->hw.mac_type < e1000_82543) ? \
|
||||
E1000_82542_##R : E1000_##R; \
|
||||
return 1; \
|
||||
} \
|
||||
} \
|
||||
static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
|
||||
int reg, uint32_t mask, uint32_t write)
|
||||
{
|
||||
static const uint32_t test[] =
|
||||
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
|
||||
uint8_t __iomem *address = adapter->hw.hw_addr + reg;
|
||||
uint32_t read;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test); i++) {
|
||||
writel(write & test[i], address);
|
||||
read = readl(address);
|
||||
if (read != (write & test[i] & mask)) {
|
||||
DPRINTK(DRV, ERR, "pattern test reg %04X failed: "
|
||||
"got 0x%08X expected 0x%08X\n",
|
||||
reg, read, (write & test[i] & mask));
|
||||
*data = reg;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define REG_SET_AND_CHECK(R, M, W) \
|
||||
{ \
|
||||
uint32_t val; \
|
||||
E1000_WRITE_REG(&adapter->hw, R, W & M); \
|
||||
val = E1000_READ_REG(&adapter->hw, R); \
|
||||
if ((W & M) != (val & M)) { \
|
||||
DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
|
||||
"expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \
|
||||
*data = (adapter->hw.mac_type < e1000_82543) ? \
|
||||
E1000_82542_##R : E1000_##R; \
|
||||
return 1; \
|
||||
} \
|
||||
static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
|
||||
int reg, uint32_t mask, uint32_t write)
|
||||
{
|
||||
uint8_t __iomem *address = adapter->hw.hw_addr + reg;
|
||||
uint32_t read;
|
||||
|
||||
writel(write & mask, address);
|
||||
read = readl(address);
|
||||
if ((read & mask) != (write & mask)) {
|
||||
DPRINTK(DRV, ERR, "set/check reg %04X test failed: "
|
||||
"got 0x%08X expected 0x%08X\n",
|
||||
reg, (read & mask), (write & mask));
|
||||
*data = reg;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define REG_PATTERN_TEST(reg, mask, write) \
|
||||
do { \
|
||||
if (reg_pattern_test(adapter, data, \
|
||||
(adapter->hw.mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg, \
|
||||
mask, write)) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define REG_SET_AND_CHECK(reg, mask, write) \
|
||||
do { \
|
||||
if (reg_set_and_check(adapter, data, \
|
||||
(adapter->hw.mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg, \
|
||||
mask, write)) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
|
||||
{
|
||||
|
|
|
@ -421,8 +421,6 @@ void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, u
|
|||
void e1000_get_bus_info(struct e1000_hw *hw);
|
||||
void e1000_pci_set_mwi(struct e1000_hw *hw);
|
||||
void e1000_pci_clear_mwi(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);
|
||||
int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value);
|
||||
void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
|
||||
int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
|
||||
|
@ -595,35 +593,35 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
|
|||
|
||||
/* Receive Descriptor */
|
||||
struct e1000_rx_desc {
|
||||
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
|
||||
uint16_t length; /* Length of data DMAed into data buffer */
|
||||
uint16_t csum; /* Packet checksum */
|
||||
__le64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
__le16 length; /* Length of data DMAed into data buffer */
|
||||
__le16 csum; /* Packet checksum */
|
||||
uint8_t status; /* Descriptor status */
|
||||
uint8_t errors; /* Descriptor Errors */
|
||||
uint16_t special;
|
||||
__le16 special;
|
||||
};
|
||||
|
||||
/* Receive Descriptor - Extended */
|
||||
union e1000_rx_desc_extended {
|
||||
struct {
|
||||
uint64_t buffer_addr;
|
||||
uint64_t reserved;
|
||||
__le64 buffer_addr;
|
||||
__le64 reserved;
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
uint32_t mrq; /* Multiple Rx Queues */
|
||||
__le32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
uint32_t rss; /* RSS Hash */
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
uint16_t ip_id; /* IP id */
|
||||
uint16_t csum; /* Packet Checksum */
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
uint32_t status_error; /* ext status/error */
|
||||
uint16_t length;
|
||||
uint16_t vlan; /* VLAN tag */
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length;
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
@ -633,29 +631,29 @@ union e1000_rx_desc_extended {
|
|||
union e1000_rx_desc_packet_split {
|
||||
struct {
|
||||
/* one buffer for protocol header(s), three data buffers */
|
||||
uint64_t buffer_addr[MAX_PS_BUFFERS];
|
||||
__le64 buffer_addr[MAX_PS_BUFFERS];
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
uint32_t mrq; /* Multiple Rx Queues */
|
||||
__le32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
uint32_t rss; /* RSS Hash */
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
uint16_t ip_id; /* IP id */
|
||||
uint16_t csum; /* Packet Checksum */
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
uint32_t status_error; /* ext status/error */
|
||||
uint16_t length0; /* length of buffer 0 */
|
||||
uint16_t vlan; /* VLAN tag */
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length0; /* length of buffer 0 */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} middle;
|
||||
struct {
|
||||
uint16_t header_status;
|
||||
uint16_t length[3]; /* length of buffers 1-3 */
|
||||
__le16 header_status;
|
||||
__le16 length[3]; /* length of buffers 1-3 */
|
||||
} upper;
|
||||
uint64_t reserved;
|
||||
__le64 reserved;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
|
@ -715,21 +713,21 @@ union e1000_rx_desc_packet_split {
|
|||
|
||||
/* Transmit Descriptor */
|
||||
struct e1000_tx_desc {
|
||||
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
|
||||
__le64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
union {
|
||||
uint32_t data;
|
||||
__le32 data;
|
||||
struct {
|
||||
uint16_t length; /* Data buffer length */
|
||||
__le16 length; /* Data buffer length */
|
||||
uint8_t cso; /* Checksum offset */
|
||||
uint8_t cmd; /* Descriptor control */
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
uint32_t data;
|
||||
__le32 data;
|
||||
struct {
|
||||
uint8_t status; /* Descriptor status */
|
||||
uint8_t css; /* Checksum start */
|
||||
uint16_t special;
|
||||
__le16 special;
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
@ -759,49 +757,49 @@ struct e1000_tx_desc {
|
|||
/* Offload Context Descriptor */
|
||||
struct e1000_context_desc {
|
||||
union {
|
||||
uint32_t ip_config;
|
||||
__le32 ip_config;
|
||||
struct {
|
||||
uint8_t ipcss; /* IP checksum start */
|
||||
uint8_t ipcso; /* IP checksum offset */
|
||||
uint16_t ipcse; /* IP checksum end */
|
||||
__le16 ipcse; /* IP checksum end */
|
||||
} ip_fields;
|
||||
} lower_setup;
|
||||
union {
|
||||
uint32_t tcp_config;
|
||||
__le32 tcp_config;
|
||||
struct {
|
||||
uint8_t tucss; /* TCP checksum start */
|
||||
uint8_t tucso; /* TCP checksum offset */
|
||||
uint16_t tucse; /* TCP checksum end */
|
||||
__le16 tucse; /* TCP checksum end */
|
||||
} tcp_fields;
|
||||
} upper_setup;
|
||||
uint32_t cmd_and_length; /* */
|
||||
__le32 cmd_and_length; /* */
|
||||
union {
|
||||
uint32_t data;
|
||||
__le32 data;
|
||||
struct {
|
||||
uint8_t status; /* Descriptor status */
|
||||
uint8_t hdr_len; /* Header length */
|
||||
uint16_t mss; /* Maximum segment size */
|
||||
__le16 mss; /* Maximum segment size */
|
||||
} fields;
|
||||
} tcp_seg_setup;
|
||||
};
|
||||
|
||||
/* Offload data descriptor */
|
||||
struct e1000_data_desc {
|
||||
uint64_t buffer_addr; /* Address of the descriptor's buffer address */
|
||||
__le64 buffer_addr; /* Address of the descriptor's buffer address */
|
||||
union {
|
||||
uint32_t data;
|
||||
__le32 data;
|
||||
struct {
|
||||
uint16_t length; /* Data buffer length */
|
||||
__le16 length; /* Data buffer length */
|
||||
uint8_t typ_len_ext; /* */
|
||||
uint8_t cmd; /* */
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
uint32_t data;
|
||||
__le32 data;
|
||||
struct {
|
||||
uint8_t status; /* Descriptor status */
|
||||
uint8_t popts; /* Packet Options */
|
||||
uint16_t special; /* */
|
||||
__le16 special; /* */
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
@ -817,8 +815,8 @@ struct e1000_data_desc {
|
|||
|
||||
/* Receive Address Register */
|
||||
struct e1000_rar {
|
||||
volatile uint32_t low; /* receive address low */
|
||||
volatile uint32_t high; /* receive address high */
|
||||
volatile __le32 low; /* receive address low */
|
||||
volatile __le32 high; /* receive address high */
|
||||
};
|
||||
|
||||
/* Number of entries in the Multicast Table Array (MTA). */
|
||||
|
|
|
@ -73,14 +73,6 @@ static struct pci_device_id e1000_pci_tbl[] = {
|
|||
INTEL_E1000_ETHERNET_DEVICE(0x1026),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1027),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1028),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1049),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x104A),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x104B),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x104C),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x104D),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x105E),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x105F),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1060),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1075),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1076),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1077),
|
||||
|
@ -89,28 +81,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
|
|||
INTEL_E1000_ETHERNET_DEVICE(0x107A),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x107B),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x107C),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x107D),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x107E),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x107F),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x108A),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x108B),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x108C),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1096),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1098),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x1099),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x109A),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10A4),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10A5),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10B5),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10B9),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10BA),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10BB),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10BC),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10C4),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10C5),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10D5),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10D9),
|
||||
INTEL_E1000_ETHERNET_DEVICE(0x10DA),
|
||||
/* required last entry */
|
||||
{0,}
|
||||
};
|
||||
|
@ -153,7 +126,7 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
|
|||
struct e1000_tx_ring *tx_ring);
|
||||
static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring);
|
||||
static void e1000_set_multi(struct net_device *netdev);
|
||||
static void e1000_set_rx_mode(struct net_device *netdev);
|
||||
static void e1000_update_phy_info(unsigned long data);
|
||||
static void e1000_watchdog(unsigned long data);
|
||||
static void e1000_82547_tx_fifo_stall(unsigned long data);
|
||||
|
@ -299,14 +272,14 @@ module_exit(e1000_exit_module);
|
|||
static int e1000_request_irq(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
void (*handler) = &e1000_intr;
|
||||
irq_handler_t handler = e1000_intr;
|
||||
int irq_flags = IRQF_SHARED;
|
||||
int err;
|
||||
|
||||
if (adapter->hw.mac_type >= e1000_82571) {
|
||||
adapter->have_msi = !pci_enable_msi(adapter->pdev);
|
||||
if (adapter->have_msi) {
|
||||
handler = &e1000_intr_msi;
|
||||
handler = e1000_intr_msi;
|
||||
irq_flags = 0;
|
||||
}
|
||||
}
|
||||
|
@ -514,7 +487,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
int i;
|
||||
|
||||
e1000_set_multi(netdev);
|
||||
e1000_set_rx_mode(netdev);
|
||||
|
||||
e1000_restore_vlan(adapter);
|
||||
e1000_init_manageability(adapter);
|
||||
|
@ -844,6 +817,64 @@ e1000_reset(struct e1000_adapter *adapter)
|
|||
e1000_release_manageability(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the eeprom for users having checksum issues
|
||||
**/
|
||||
void e1000_dump_eeprom(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct ethtool_eeprom eeprom;
|
||||
const struct ethtool_ops *ops = netdev->ethtool_ops;
|
||||
u8 *data;
|
||||
int i;
|
||||
u16 csum_old, csum_new = 0;
|
||||
|
||||
eeprom.len = ops->get_eeprom_len(netdev);
|
||||
eeprom.offset = 0;
|
||||
|
||||
data = kmalloc(eeprom.len, GFP_KERNEL);
|
||||
if (!data) {
|
||||
printk(KERN_ERR "Unable to allocate memory to dump EEPROM"
|
||||
" data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ops->get_eeprom(netdev, &eeprom, data);
|
||||
|
||||
csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
|
||||
(data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
|
||||
for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
|
||||
csum_new += data[i] + (data[i + 1] << 8);
|
||||
csum_new = EEPROM_SUM - csum_new;
|
||||
|
||||
printk(KERN_ERR "/*********************/\n");
|
||||
printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old);
|
||||
printk(KERN_ERR "Calculated : 0x%04x\n", csum_new);
|
||||
|
||||
printk(KERN_ERR "Offset Values\n");
|
||||
printk(KERN_ERR "======== ======\n");
|
||||
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
|
||||
|
||||
printk(KERN_ERR "Include this output when contacting your support "
|
||||
"provider.\n");
|
||||
printk(KERN_ERR "This is not a software error! Something bad "
|
||||
"happened to your hardware or\n");
|
||||
printk(KERN_ERR "EEPROM image. Ignoring this "
|
||||
"problem could result in further problems,\n");
|
||||
printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n");
|
||||
printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, "
|
||||
"which is invalid\n");
|
||||
printk(KERN_ERR "and requires you to set the proper MAC "
|
||||
"address manually before continuing\n");
|
||||
printk(KERN_ERR "to enable this network device.\n");
|
||||
printk(KERN_ERR "Please inspect the EEPROM dump and report the issue "
|
||||
"to your hardware vendor\n");
|
||||
printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n");
|
||||
printk(KERN_ERR "/*********************/\n");
|
||||
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_probe - Device Initialization Routine
|
||||
* @pdev: PCI device information struct
|
||||
|
@ -927,7 +958,7 @@ e1000_probe(struct pci_dev *pdev,
|
|||
netdev->stop = &e1000_close;
|
||||
netdev->hard_start_xmit = &e1000_xmit_frame;
|
||||
netdev->get_stats = &e1000_get_stats;
|
||||
netdev->set_multicast_list = &e1000_set_multi;
|
||||
netdev->set_rx_mode = &e1000_set_rx_mode;
|
||||
netdev->set_mac_address = &e1000_set_mac;
|
||||
netdev->change_mtu = &e1000_change_mtu;
|
||||
netdev->do_ioctl = &e1000_ioctl;
|
||||
|
@ -995,7 +1026,6 @@ e1000_probe(struct pci_dev *pdev,
|
|||
adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
|
||||
|
||||
/* initialize eeprom parameters */
|
||||
|
||||
if (e1000_init_eeprom_params(&adapter->hw)) {
|
||||
E1000_ERR("EEPROM initialization failed\n");
|
||||
goto err_eeprom;
|
||||
|
@ -1007,23 +1037,29 @@ e1000_probe(struct pci_dev *pdev,
|
|||
e1000_reset_hw(&adapter->hw);
|
||||
|
||||
/* make sure the EEPROM is good */
|
||||
|
||||
if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
|
||||
DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
|
||||
goto err_eeprom;
|
||||
e1000_dump_eeprom(adapter);
|
||||
/*
|
||||
* set MAC address to all zeroes to invalidate and temporary
|
||||
* disable this device for the user. This blocks regular
|
||||
* traffic while still permitting ethtool ioctls from reaching
|
||||
* the hardware as well as allowing the user to run the
|
||||
* interface after manually setting a hw addr using
|
||||
* `ip set address`
|
||||
*/
|
||||
memset(adapter->hw.mac_addr, 0, netdev->addr_len);
|
||||
} else {
|
||||
/* copy the MAC address out of the EEPROM */
|
||||
if (e1000_read_mac_addr(&adapter->hw))
|
||||
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
|
||||
}
|
||||
|
||||
/* copy the MAC address out of the EEPROM */
|
||||
|
||||
if (e1000_read_mac_addr(&adapter->hw))
|
||||
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
|
||||
/* don't block initalization here due to bad MAC address */
|
||||
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
|
||||
memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
|
||||
|
||||
if (!is_valid_ether_addr(netdev->perm_addr)) {
|
||||
if (!is_valid_ether_addr(netdev->perm_addr))
|
||||
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
|
||||
goto err_eeprom;
|
||||
}
|
||||
|
||||
e1000_get_bus_info(&adapter->hw);
|
||||
|
||||
|
@ -2410,21 +2446,22 @@ e1000_set_mac(struct net_device *netdev, void *p)
|
|||
}
|
||||
|
||||
/**
|
||||
* e1000_set_multi - Multicast and Promiscuous mode set
|
||||
* e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* The set_multi entry point is called whenever the multicast address
|
||||
* list or the network interface flags are updated. This routine is
|
||||
* responsible for configuring the hardware for proper multicast,
|
||||
* The set_rx_mode entry point is called whenever the unicast or multicast
|
||||
* address lists or the network interface flags are updated. This routine is
|
||||
* responsible for configuring the hardware for proper unicast, multicast,
|
||||
* promiscuous mode, and all-multi behavior.
|
||||
**/
|
||||
|
||||
static void
|
||||
e1000_set_multi(struct net_device *netdev)
|
||||
e1000_set_rx_mode(struct net_device *netdev)
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct dev_mc_list *mc_ptr;
|
||||
struct dev_addr_list *uc_ptr;
|
||||
struct dev_addr_list *mc_ptr;
|
||||
uint32_t rctl;
|
||||
uint32_t hash_value;
|
||||
int i, rar_entries = E1000_RAR_ENTRIES;
|
||||
|
@ -2447,9 +2484,16 @@ e1000_set_multi(struct net_device *netdev)
|
|||
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
|
||||
} else if (netdev->flags & IFF_ALLMULTI) {
|
||||
rctl |= E1000_RCTL_MPE;
|
||||
rctl &= ~E1000_RCTL_UPE;
|
||||
} else {
|
||||
rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
|
||||
rctl &= ~E1000_RCTL_MPE;
|
||||
}
|
||||
|
||||
uc_ptr = NULL;
|
||||
if (netdev->uc_count > rar_entries - 1) {
|
||||
rctl |= E1000_RCTL_UPE;
|
||||
} else if (!(netdev->flags & IFF_PROMISC)) {
|
||||
rctl &= ~E1000_RCTL_UPE;
|
||||
uc_ptr = netdev->uc_list;
|
||||
}
|
||||
|
||||
E1000_WRITE_REG(hw, RCTL, rctl);
|
||||
|
@ -2459,7 +2503,10 @@ e1000_set_multi(struct net_device *netdev)
|
|||
if (hw->mac_type == e1000_82542_rev2_0)
|
||||
e1000_enter_82542_rst(adapter);
|
||||
|
||||
/* load the first 14 multicast address into the exact filters 1-14
|
||||
/* load the first 14 addresses into the exact filters 1-14. Unicast
|
||||
* addresses take precedence to avoid disabling unicast filtering
|
||||
* when possible.
|
||||
*
|
||||
* RAR 0 is used for the station MAC adddress
|
||||
* if there are not 14 addresses, go ahead and clear the filters
|
||||
* -- with 82571 controllers only 0-13 entries are filled here
|
||||
|
@ -2467,8 +2514,11 @@ e1000_set_multi(struct net_device *netdev)
|
|||
mc_ptr = netdev->mc_list;
|
||||
|
||||
for (i = 1; i < rar_entries; i++) {
|
||||
if (mc_ptr) {
|
||||
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
|
||||
if (uc_ptr) {
|
||||
e1000_rar_set(hw, uc_ptr->da_addr, i);
|
||||
uc_ptr = uc_ptr->next;
|
||||
} else if (mc_ptr) {
|
||||
e1000_rar_set(hw, mc_ptr->da_addr, i);
|
||||
mc_ptr = mc_ptr->next;
|
||||
} else {
|
||||
E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
|
||||
|
@ -2477,6 +2527,7 @@ e1000_set_multi(struct net_device *netdev)
|
|||
E1000_WRITE_FLUSH(hw);
|
||||
}
|
||||
}
|
||||
WARN_ON(uc_ptr != NULL);
|
||||
|
||||
/* clear the old settings from the multicast hash table */
|
||||
|
||||
|
@ -2488,7 +2539,7 @@ e1000_set_multi(struct net_device *netdev)
|
|||
/* load any remaining addresses into the hash table */
|
||||
|
||||
for (; mc_ptr; mc_ptr = mc_ptr->next) {
|
||||
hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr);
|
||||
hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr);
|
||||
e1000_mta_set(hw, hash_value);
|
||||
}
|
||||
|
||||
|
@ -3680,10 +3731,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
|
|||
}
|
||||
|
||||
/* Fill out the OS statistics structure */
|
||||
adapter->net_stats.rx_packets = adapter->stats.gprc;
|
||||
adapter->net_stats.tx_packets = adapter->stats.gptc;
|
||||
adapter->net_stats.rx_bytes = adapter->stats.gorcl;
|
||||
adapter->net_stats.tx_bytes = adapter->stats.gotcl;
|
||||
adapter->net_stats.multicast = adapter->stats.mprc;
|
||||
adapter->net_stats.collisions = adapter->stats.colc;
|
||||
|
||||
|
@ -4059,6 +4106,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
|||
}
|
||||
adapter->total_tx_bytes += total_tx_bytes;
|
||||
adapter->total_tx_packets += total_tx_packets;
|
||||
adapter->net_stats.tx_bytes += total_tx_bytes;
|
||||
adapter->net_stats.tx_packets += total_tx_packets;
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -4106,8 +4155,8 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
|
|||
/* Hardware complements the payload checksum, so we undo it
|
||||
* and then put the value in host order for further stack use.
|
||||
*/
|
||||
csum = ntohl(csum ^ 0xFFFF);
|
||||
skb->csum = csum;
|
||||
__sum16 sum = (__force __sum16)htons(csum);
|
||||
skb->csum = csum_unfold(~sum);
|
||||
skb->ip_summed = CHECKSUM_COMPLETE;
|
||||
}
|
||||
adapter->hw_csum_good++;
|
||||
|
@ -4281,6 +4330,8 @@ next_desc:
|
|||
|
||||
adapter->total_rx_packets += total_rx_packets;
|
||||
adapter->total_rx_bytes += total_rx_bytes;
|
||||
adapter->net_stats.rx_bytes += total_rx_bytes;
|
||||
adapter->net_stats.rx_packets += total_rx_packets;
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -4468,6 +4519,8 @@ next_desc:
|
|||
|
||||
adapter->total_rx_packets += total_rx_packets;
|
||||
adapter->total_rx_bytes += total_rx_bytes;
|
||||
adapter->net_stats.rx_bytes += total_rx_bytes;
|
||||
adapter->net_stats.rx_packets += total_rx_packets;
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -4631,7 +4684,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
|
|||
rx_desc->read.buffer_addr[j+1] =
|
||||
cpu_to_le64(ps_page_dma->ps_page_dma[j]);
|
||||
} else
|
||||
rx_desc->read.buffer_addr[j+1] = ~0;
|
||||
rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0);
|
||||
}
|
||||
|
||||
skb = netdev_alloc_skb(netdev,
|
||||
|
@ -4874,22 +4927,6 @@ e1000_pci_clear_mwi(struct e1000_hw *hw)
|
|||
pci_clear_mwi(adapter->pdev);
|
||||
}
|
||||
|
||||
void
|
||||
e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
|
||||
pci_read_config_word(adapter->pdev, reg, value);
|
||||
}
|
||||
|
||||
void
|
||||
e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
|
||||
{
|
||||
struct e1000_adapter *adapter = hw->back;
|
||||
|
||||
pci_write_config_word(adapter->pdev, reg, *value);
|
||||
}
|
||||
|
||||
int
|
||||
e1000_pcix_get_mmrbc(struct e1000_hw *hw)
|
||||
{
|
||||
|
@ -5095,7 +5132,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
|
||||
if (wufc) {
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_set_multi(netdev);
|
||||
e1000_set_rx_mode(netdev);
|
||||
|
||||
/* turn on all-multi mode if wake on multicast is enabled */
|
||||
if (wufc & E1000_WUFC_MC) {
|
||||
|
|
|
@ -194,6 +194,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
|
|||
break;
|
||||
case E1000_DEV_ID_82571EB_SERDES:
|
||||
case E1000_DEV_ID_82572EI_SERDES:
|
||||
case E1000_DEV_ID_82571EB_SERDES_DUAL:
|
||||
case E1000_DEV_ID_82571EB_SERDES_QUAD:
|
||||
hw->media_type = e1000_media_type_internal_serdes;
|
||||
break;
|
||||
default:
|
||||
|
@ -260,6 +262,7 @@ static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter)
|
|||
case E1000_DEV_ID_82571EB_QUAD_COPPER:
|
||||
case E1000_DEV_ID_82571EB_QUAD_FIBER:
|
||||
case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
|
||||
case E1000_DEV_ID_82571PT_QUAD_COPPER:
|
||||
adapter->flags |= FLAG_IS_QUAD_PORT;
|
||||
/* mark the first port */
|
||||
if (global_quad_port_a == 0)
|
||||
|
@ -285,6 +288,9 @@ static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter)
|
|||
if (adapter->flags & FLAG_IS_QUAD_PORT &&
|
||||
(!(adapter->flags & FLAG_IS_QUAD_PORT_A)))
|
||||
adapter->flags &= ~FLAG_HAS_WOL;
|
||||
/* Does not support WoL on any port */
|
||||
if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)
|
||||
adapter->flags &= ~FLAG_HAS_WOL;
|
||||
break;
|
||||
|
||||
case e1000_82573:
|
||||
|
@ -752,6 +758,10 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
|
|||
ew32(IMC, 0xffffffff);
|
||||
icr = er32(ICR);
|
||||
|
||||
if (hw->mac.type == e1000_82571 &&
|
||||
hw->dev_spec.e82571.alt_mac_addr_is_present)
|
||||
e1000e_set_laa_state_82571(hw, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1339,7 +1349,6 @@ struct e1000_info e1000_82573_info = {
|
|||
| FLAG_HAS_STATS_ICR_ICT
|
||||
| FLAG_HAS_SMART_POWER_DOWN
|
||||
| FLAG_HAS_AMT
|
||||
| FLAG_HAS_ASPM
|
||||
| FLAG_HAS_ERT
|
||||
| FLAG_HAS_SWSM_ON_LOAD,
|
||||
.pba = 20,
|
||||
|
|
|
@ -557,6 +557,7 @@
|
|||
#define NVM_INIT_3GIO_3 0x001A
|
||||
#define NVM_INIT_CONTROL3_PORT_A 0x0024
|
||||
#define NVM_CFG 0x0012
|
||||
#define NVM_ALT_MAC_ADDR_PTR 0x0037
|
||||
#define NVM_CHECKSUM_REG 0x003F
|
||||
|
||||
#define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */
|
||||
|
|
|
@ -288,7 +288,6 @@ struct e1000_info {
|
|||
#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
|
||||
#define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
|
||||
#define FLAG_HAS_JUMBO_FRAMES (1 << 7)
|
||||
#define FLAG_HAS_ASPM (1 << 8)
|
||||
#define FLAG_HAS_STATS_ICR_ICT (1 << 9)
|
||||
#define FLAG_HAS_STATS_PTC_PRC (1 << 10)
|
||||
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
|
||||
|
|
|
@ -95,15 +95,14 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
|
|||
{ "tx_dma_failed", E1000_STAT(tx_dma_failed) },
|
||||
};
|
||||
|
||||
#define E1000_GLOBAL_STATS_LEN \
|
||||
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
|
||||
#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
|
||||
#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN)
|
||||
static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
|
||||
"Register test (offline)", "Eeprom test (offline)",
|
||||
"Interrupt test (offline)", "Loopback test (offline)",
|
||||
"Link test (on/offline)"
|
||||
};
|
||||
#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
|
||||
#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
|
||||
|
||||
static int e1000_get_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *ecmd)
|
||||
|
@ -691,41 +690,63 @@ err_setup:
|
|||
return err;
|
||||
}
|
||||
|
||||
#define REG_PATTERN_TEST(R, M, W) REG_PATTERN_TEST_ARRAY(R, 0, M, W)
|
||||
#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, writeable) \
|
||||
{ \
|
||||
u32 _pat; \
|
||||
u32 _value; \
|
||||
u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
|
||||
for (_pat = 0; _pat < ARRAY_SIZE(_test); _pat++) { \
|
||||
E1000_WRITE_REG_ARRAY(hw, reg, offset, \
|
||||
(_test[_pat] & writeable)); \
|
||||
_value = E1000_READ_REG_ARRAY(hw, reg, offset); \
|
||||
if (_value != (_test[_pat] & writeable & mask)) { \
|
||||
ndev_err(netdev, "pattern test reg %04X " \
|
||||
"failed: got 0x%08X expected 0x%08X\n", \
|
||||
reg + offset, \
|
||||
value, (_test[_pat] & writeable & mask)); \
|
||||
*data = reg; \
|
||||
return 1; \
|
||||
} \
|
||||
} \
|
||||
bool reg_pattern_test_array(struct e1000_adapter *adapter, u64 *data,
|
||||
int reg, int offset, u32 mask, u32 write)
|
||||
{
|
||||
int i;
|
||||
u32 read;
|
||||
static const u32 test[] =
|
||||
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
|
||||
for (i = 0; i < ARRAY_SIZE(test); i++) {
|
||||
E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
|
||||
(test[i] & write));
|
||||
read = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
|
||||
if (read != (test[i] & write & mask)) {
|
||||
ndev_err(adapter->netdev, "pattern test reg %04X "
|
||||
"failed: got 0x%08X expected 0x%08X\n",
|
||||
reg + offset,
|
||||
read, (test[i] & write & mask));
|
||||
*data = reg;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define REG_SET_AND_CHECK(R, M, W) \
|
||||
{ \
|
||||
u32 _value; \
|
||||
__ew32(hw, R, W & M); \
|
||||
_value = __er32(hw, R); \
|
||||
if ((W & M) != (_value & M)) { \
|
||||
ndev_err(netdev, "set/check reg %04X test failed: " \
|
||||
"got 0x%08X expected 0x%08X\n", R, (_value & M), \
|
||||
(W & M)); \
|
||||
*data = R; \
|
||||
return 1; \
|
||||
} \
|
||||
static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
|
||||
int reg, u32 mask, u32 write)
|
||||
{
|
||||
u32 read;
|
||||
__ew32(&adapter->hw, reg, write & mask);
|
||||
read = __er32(&adapter->hw, reg);
|
||||
if ((write & mask) != (read & mask)) {
|
||||
ndev_err(adapter->netdev, "set/check reg %04X test failed: "
|
||||
"got 0x%08X expected 0x%08X\n", reg, (read & mask),
|
||||
(write & mask));
|
||||
*data = reg;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define REG_PATTERN_TEST(R, M, W) \
|
||||
do { \
|
||||
if (reg_pattern_test_array(adapter, data, R, 0, M, W)) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define REG_PATTERN_TEST_ARRAY(R, offset, M, W) \
|
||||
do { \
|
||||
if (reg_pattern_test_array(adapter, data, R, offset, M, W)) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define REG_SET_AND_CHECK(R, M, W) \
|
||||
do { \
|
||||
if (reg_set_and_check(adapter, data, R, M, W)) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
|
|
@ -303,8 +303,11 @@ enum e1e_registers {
|
|||
#define E1000_DEV_ID_82571EB_FIBER 0x105F
|
||||
#define E1000_DEV_ID_82571EB_SERDES 0x1060
|
||||
#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
|
||||
#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
|
||||
#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5
|
||||
#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC
|
||||
#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
|
||||
#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA
|
||||
#define E1000_DEV_ID_82572EI_COPPER 0x107D
|
||||
#define E1000_DEV_ID_82572EI_FIBER 0x107E
|
||||
#define E1000_DEV_ID_82572EI_SERDES 0x107F
|
||||
|
@ -420,35 +423,35 @@ enum e1000_smart_speed {
|
|||
|
||||
/* Receive Descriptor */
|
||||
struct e1000_rx_desc {
|
||||
u64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
u16 length; /* Length of data DMAed into data buffer */
|
||||
u16 csum; /* Packet checksum */
|
||||
__le64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
__le16 length; /* Length of data DMAed into data buffer */
|
||||
__le16 csum; /* Packet checksum */
|
||||
u8 status; /* Descriptor status */
|
||||
u8 errors; /* Descriptor Errors */
|
||||
u16 special;
|
||||
__le16 special;
|
||||
};
|
||||
|
||||
/* Receive Descriptor - Extended */
|
||||
union e1000_rx_desc_extended {
|
||||
struct {
|
||||
u64 buffer_addr;
|
||||
u64 reserved;
|
||||
__le64 buffer_addr;
|
||||
__le64 reserved;
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
u32 mrq; /* Multiple Rx Queues */
|
||||
__le32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length;
|
||||
u16 vlan; /* VLAN tag */
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length;
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
@ -458,49 +461,49 @@ union e1000_rx_desc_extended {
|
|||
union e1000_rx_desc_packet_split {
|
||||
struct {
|
||||
/* one buffer for protocol header(s), three data buffers */
|
||||
u64 buffer_addr[MAX_PS_BUFFERS];
|
||||
__le64 buffer_addr[MAX_PS_BUFFERS];
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
u32 mrq; /* Multiple Rx Queues */
|
||||
__le32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length0; /* length of buffer 0 */
|
||||
u16 vlan; /* VLAN tag */
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length0; /* length of buffer 0 */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} middle;
|
||||
struct {
|
||||
u16 header_status;
|
||||
u16 length[3]; /* length of buffers 1-3 */
|
||||
__le16 header_status;
|
||||
__le16 length[3]; /* length of buffers 1-3 */
|
||||
} upper;
|
||||
u64 reserved;
|
||||
__le64 reserved;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Transmit Descriptor */
|
||||
struct e1000_tx_desc {
|
||||
u64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
__le64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
union {
|
||||
u32 data;
|
||||
__le32 data;
|
||||
struct {
|
||||
u16 length; /* Data buffer length */
|
||||
__le16 length; /* Data buffer length */
|
||||
u8 cso; /* Checksum offset */
|
||||
u8 cmd; /* Descriptor control */
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
u32 data;
|
||||
__le32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 css; /* Checksum start */
|
||||
u16 special;
|
||||
__le16 special;
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
@ -508,49 +511,49 @@ struct e1000_tx_desc {
|
|||
/* Offload Context Descriptor */
|
||||
struct e1000_context_desc {
|
||||
union {
|
||||
u32 ip_config;
|
||||
__le32 ip_config;
|
||||
struct {
|
||||
u8 ipcss; /* IP checksum start */
|
||||
u8 ipcso; /* IP checksum offset */
|
||||
u16 ipcse; /* IP checksum end */
|
||||
__le16 ipcse; /* IP checksum end */
|
||||
} ip_fields;
|
||||
} lower_setup;
|
||||
union {
|
||||
u32 tcp_config;
|
||||
__le32 tcp_config;
|
||||
struct {
|
||||
u8 tucss; /* TCP checksum start */
|
||||
u8 tucso; /* TCP checksum offset */
|
||||
u16 tucse; /* TCP checksum end */
|
||||
__le16 tucse; /* TCP checksum end */
|
||||
} tcp_fields;
|
||||
} upper_setup;
|
||||
u32 cmd_and_length;
|
||||
__le32 cmd_and_length;
|
||||
union {
|
||||
u32 data;
|
||||
__le32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 hdr_len; /* Header length */
|
||||
u16 mss; /* Maximum segment size */
|
||||
__le16 mss; /* Maximum segment size */
|
||||
} fields;
|
||||
} tcp_seg_setup;
|
||||
};
|
||||
|
||||
/* Offload data descriptor */
|
||||
struct e1000_data_desc {
|
||||
u64 buffer_addr; /* Address of the descriptor's buffer address */
|
||||
__le64 buffer_addr; /* Address of the descriptor's buffer address */
|
||||
union {
|
||||
u32 data;
|
||||
__le32 data;
|
||||
struct {
|
||||
u16 length; /* Data buffer length */
|
||||
__le16 length; /* Data buffer length */
|
||||
u8 typ_len_ext;
|
||||
u8 cmd;
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
u32 data;
|
||||
__le32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 popts; /* Packet Options */
|
||||
u16 special; /* */
|
||||
__le16 special; /* */
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
@ -816,6 +819,7 @@ struct e1000_bus_info {
|
|||
|
||||
struct e1000_dev_spec_82571 {
|
||||
bool laa_is_present;
|
||||
bool alt_mac_addr_is_present;
|
||||
};
|
||||
|
||||
struct e1000_shadow_ram {
|
||||
|
|
|
@ -2059,9 +2059,44 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
|
|||
{
|
||||
s32 ret_val;
|
||||
u16 offset, nvm_data, i;
|
||||
u16 mac_addr_offset = 0;
|
||||
|
||||
if (hw->mac.type == e1000_82571) {
|
||||
/* Check for an alternate MAC address. An alternate MAC
|
||||
* address can be setup by pre-boot software and must be
|
||||
* treated like a permanent address and must override the
|
||||
* actual permanent MAC address. */
|
||||
ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
|
||||
&mac_addr_offset);
|
||||
if (ret_val) {
|
||||
hw_dbg(hw, "NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
if (mac_addr_offset == 0xFFFF)
|
||||
mac_addr_offset = 0;
|
||||
|
||||
if (mac_addr_offset) {
|
||||
if (hw->bus.func == E1000_FUNC_1)
|
||||
mac_addr_offset += ETH_ALEN/sizeof(u16);
|
||||
|
||||
/* make sure we have a valid mac address here
|
||||
* before using it */
|
||||
ret_val = e1000_read_nvm(hw, mac_addr_offset, 1,
|
||||
&nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg(hw, "NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
if (nvm_data & 0x0001)
|
||||
mac_addr_offset = 0;
|
||||
}
|
||||
|
||||
if (mac_addr_offset)
|
||||
hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i += 2) {
|
||||
offset = i >> 1;
|
||||
offset = mac_addr_offset + (i >> 1);
|
||||
ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg(hw, "NVM Read Error\n");
|
||||
|
@ -2072,7 +2107,7 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
|
|||
}
|
||||
|
||||
/* Flip last bit of mac address if we're on second port */
|
||||
if (hw->bus.func == E1000_FUNC_1)
|
||||
if (!mac_addr_offset && hw->bus.func == E1000_FUNC_1)
|
||||
hw->mac.perm_addr[5] ^= 1;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
|
|
|
@ -91,7 +91,7 @@ static int e1000_desc_unused(struct e1000_ring *ring)
|
|||
static void e1000_receive_skb(struct e1000_adapter *adapter,
|
||||
struct net_device *netdev,
|
||||
struct sk_buff *skb,
|
||||
u8 status, u16 vlan)
|
||||
u8 status, __le16 vlan)
|
||||
{
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
|
||||
|
@ -142,8 +142,8 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
|
|||
/* Hardware complements the payload checksum, so we undo it
|
||||
* and then put the value in host order for further stack use.
|
||||
*/
|
||||
csum = ntohl(csum ^ 0xFFFF);
|
||||
skb->csum = csum;
|
||||
__sum16 sum = (__force __sum16)htons(csum);
|
||||
skb->csum = csum_unfold(~sum);
|
||||
skb->ip_summed = CHECKSUM_COMPLETE;
|
||||
}
|
||||
adapter->hw_csum_good++;
|
||||
|
@ -248,7 +248,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
|
|||
ps_page = &buffer_info->ps_pages[j];
|
||||
if (j >= adapter->rx_ps_pages) {
|
||||
/* all unused desc entries get hw null ptr */
|
||||
rx_desc->read.buffer_addr[j+1] = ~0;
|
||||
rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0);
|
||||
continue;
|
||||
}
|
||||
if (!ps_page->page) {
|
||||
|
@ -458,6 +458,8 @@ next_desc:
|
|||
|
||||
adapter->total_rx_packets += total_rx_packets;
|
||||
adapter->total_rx_bytes += total_rx_bytes;
|
||||
adapter->net_stats.rx_packets += total_rx_packets;
|
||||
adapter->net_stats.rx_bytes += total_rx_bytes;
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -593,6 +595,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
|
|||
}
|
||||
adapter->total_tx_bytes += total_tx_bytes;
|
||||
adapter->total_tx_packets += total_tx_packets;
|
||||
adapter->net_stats.tx_packets += total_tx_packets;
|
||||
adapter->net_stats.tx_bytes += total_tx_bytes;
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -755,6 +759,8 @@ next_desc:
|
|||
|
||||
adapter->total_rx_packets += total_rx_packets;
|
||||
adapter->total_rx_bytes += total_rx_bytes;
|
||||
adapter->net_stats.rx_packets += total_rx_packets;
|
||||
adapter->net_stats.rx_bytes += total_rx_bytes;
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -935,7 +941,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
|||
static int e1000_request_irq(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
void (*handler) = &e1000_intr;
|
||||
irq_handler_t handler = e1000_intr;
|
||||
int irq_flags = IRQF_SHARED;
|
||||
int err;
|
||||
|
||||
|
@ -945,7 +951,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
|
|||
"Unable to allocate MSI interrupt Error: %d\n", err);
|
||||
} else {
|
||||
adapter->flags |= FLAG_MSI_ENABLED;
|
||||
handler = &e1000_intr_msi;
|
||||
handler = e1000_intr_msi;
|
||||
irq_flags = 0;
|
||||
}
|
||||
|
||||
|
@ -2535,10 +2541,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
}
|
||||
|
||||
/* Fill out the OS statistics structure */
|
||||
adapter->net_stats.rx_packets = adapter->stats.gprc;
|
||||
adapter->net_stats.tx_packets = adapter->stats.gptc;
|
||||
adapter->net_stats.rx_bytes = adapter->stats.gorcl;
|
||||
adapter->net_stats.tx_bytes = adapter->stats.gotcl;
|
||||
adapter->net_stats.multicast = adapter->stats.mprc;
|
||||
adapter->net_stats.collisions = adapter->stats.colc;
|
||||
|
||||
|
@ -3509,6 +3511,33 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void e1000e_disable_l1aspm(struct pci_dev *pdev)
|
||||
{
|
||||
int pos;
|
||||
u32 cap;
|
||||
u16 val;
|
||||
|
||||
/*
|
||||
* 82573 workaround - disable L1 ASPM on mobile chipsets
|
||||
*
|
||||
* L1 ASPM on various mobile (ich7) chipsets do not behave properly
|
||||
* resulting in lost data or garbage information on the pci-e link
|
||||
* level. This could result in (false) bad EEPROM checksum errors,
|
||||
* long ping times (up to 2s) or even a system freeze/hang.
|
||||
*
|
||||
* Unfortunately this feature saves about 1W power consumption when
|
||||
* active.
|
||||
*/
|
||||
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
||||
pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &cap);
|
||||
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val);
|
||||
if (val & 0x2) {
|
||||
dev_warn(&pdev->dev, "Disabling L1 ASPM\n");
|
||||
val &= ~0x2;
|
||||
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int e1000_resume(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -3519,6 +3548,7 @@ static int e1000_resume(struct pci_dev *pdev)
|
|||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
e1000e_disable_l1aspm(pdev);
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
|
@ -3619,6 +3649,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
e1000e_disable_l1aspm(pdev);
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot re-enable PCI device after reset.\n");
|
||||
|
@ -3720,6 +3751,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||
u16 eeprom_data = 0;
|
||||
u16 eeprom_apme_mask = E1000_EEPROM_APME;
|
||||
|
||||
e1000e_disable_l1aspm(pdev);
|
||||
err = pci_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -4056,16 +4088,15 @@ static struct pci_error_handlers e1000_err_handler = {
|
|||
};
|
||||
|
||||
static struct pci_device_id e1000_pci_tbl[] = {
|
||||
/*
|
||||
* Support for 82571/2/3, es2lan and ich8 will be phased in
|
||||
* stepwise.
|
||||
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 },
|
||||
|
@ -4088,8 +4119,6 @@ static struct pci_device_id e1000_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
|
||||
*/
|
||||
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan },
|
||||
|
|
|
@ -262,13 +262,6 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
|
|||
.max = MAX_RXDELAY } }
|
||||
};
|
||||
|
||||
/* modify min and default if 82573 for slow ping w/a,
|
||||
* a value greater than 8 needs to be set for RDTR */
|
||||
if (adapter->flags & FLAG_HAS_ASPM) {
|
||||
opt.def = 32;
|
||||
opt.arg.r.min = 8;
|
||||
}
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
|
|
|
@ -49,8 +49,7 @@ static const u16 e1000_igp_2_cable_length_table[] =
|
|||
100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
|
||||
124};
|
||||
#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
|
||||
(sizeof(e1000_igp_2_cable_length_table) / \
|
||||
sizeof(e1000_igp_2_cable_length_table[0]))
|
||||
ARRAY_SIZE(e1000_igp_2_cable_length_table)
|
||||
|
||||
/**
|
||||
* e1000e_check_reset_block_generic - Check if PHY reset is blocked
|
||||
|
|
|
@ -304,13 +304,7 @@ enum commands {
|
|||
#if defined(__alpha__)
|
||||
# define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status);
|
||||
#else
|
||||
# if defined(__LITTLE_ENDIAN)
|
||||
# define clear_suspend(cmd) ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x4000
|
||||
# elif defined(__BIG_ENDIAN)
|
||||
# define clear_suspend(cmd) ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x0040
|
||||
# else
|
||||
# error Unsupported byteorder
|
||||
# endif
|
||||
# define clear_suspend(cmd) ((__le16 *)&(cmd)->cmd_status)[1] &= ~cpu_to_le16(1<<14)
|
||||
#endif
|
||||
|
||||
enum SCBCmdBits {
|
||||
|
@ -331,17 +325,17 @@ enum SCBPort_cmds {
|
|||
|
||||
/* The Speedo3 Rx and Tx frame/buffer descriptors. */
|
||||
struct descriptor { /* A generic descriptor. */
|
||||
volatile s32 cmd_status; /* All command and status fields. */
|
||||
u32 link; /* struct descriptor * */
|
||||
volatile __le32 cmd_status; /* All command and status fields. */
|
||||
__le32 link; /* struct descriptor * */
|
||||
unsigned char params[0];
|
||||
};
|
||||
|
||||
/* The Speedo3 Rx and Tx buffer descriptors. */
|
||||
struct RxFD { /* Receive frame descriptor. */
|
||||
volatile s32 status;
|
||||
u32 link; /* struct RxFD * */
|
||||
u32 rx_buf_addr; /* void * */
|
||||
u32 count;
|
||||
volatile __le32 status;
|
||||
__le32 link; /* struct RxFD * */
|
||||
__le32 rx_buf_addr; /* void * */
|
||||
__le32 count;
|
||||
} RxFD_ALIGNMENT;
|
||||
|
||||
/* Selected elements of the Tx/RxFD.status word. */
|
||||
|
@ -354,16 +348,16 @@ enum RxFD_bits {
|
|||
|
||||
#define CONFIG_DATA_SIZE 22
|
||||
struct TxFD { /* Transmit frame descriptor set. */
|
||||
s32 status;
|
||||
u32 link; /* void * */
|
||||
u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */
|
||||
s32 count; /* # of TBD (=1), Tx start thresh., etc. */
|
||||
__le32 status;
|
||||
__le32 link; /* void * */
|
||||
__le32 tx_desc_addr; /* Always points to the tx_buf_addr element. */
|
||||
__le32 count; /* # of TBD (=1), Tx start thresh., etc. */
|
||||
/* This constitutes two "TBD" entries -- we only use one. */
|
||||
#define TX_DESCR_BUF_OFFSET 16
|
||||
u32 tx_buf_addr0; /* void *, frame to be transmitted. */
|
||||
s32 tx_buf_size0; /* Length of Tx frame. */
|
||||
u32 tx_buf_addr1; /* void *, frame to be transmitted. */
|
||||
s32 tx_buf_size1; /* Length of Tx frame. */
|
||||
__le32 tx_buf_addr0; /* void *, frame to be transmitted. */
|
||||
__le32 tx_buf_size0; /* Length of Tx frame. */
|
||||
__le32 tx_buf_addr1; /* void *, frame to be transmitted. */
|
||||
__le32 tx_buf_size1; /* Length of Tx frame. */
|
||||
/* the structure must have space for at least CONFIG_DATA_SIZE starting
|
||||
* from tx_desc_addr field */
|
||||
};
|
||||
|
@ -379,23 +373,23 @@ struct speedo_mc_block {
|
|||
|
||||
/* Elements of the dump_statistics block. This block must be lword aligned. */
|
||||
struct speedo_stats {
|
||||
u32 tx_good_frames;
|
||||
u32 tx_coll16_errs;
|
||||
u32 tx_late_colls;
|
||||
u32 tx_underruns;
|
||||
u32 tx_lost_carrier;
|
||||
u32 tx_deferred;
|
||||
u32 tx_one_colls;
|
||||
u32 tx_multi_colls;
|
||||
u32 tx_total_colls;
|
||||
u32 rx_good_frames;
|
||||
u32 rx_crc_errs;
|
||||
u32 rx_align_errs;
|
||||
u32 rx_resource_errs;
|
||||
u32 rx_overrun_errs;
|
||||
u32 rx_colls_errs;
|
||||
u32 rx_runt_errs;
|
||||
u32 done_marker;
|
||||
__le32 tx_good_frames;
|
||||
__le32 tx_coll16_errs;
|
||||
__le32 tx_late_colls;
|
||||
__le32 tx_underruns;
|
||||
__le32 tx_lost_carrier;
|
||||
__le32 tx_deferred;
|
||||
__le32 tx_one_colls;
|
||||
__le32 tx_multi_colls;
|
||||
__le32 tx_total_colls;
|
||||
__le32 rx_good_frames;
|
||||
__le32 rx_crc_errs;
|
||||
__le32 rx_align_errs;
|
||||
__le32 rx_resource_errs;
|
||||
__le32 rx_overrun_errs;
|
||||
__le32 rx_colls_errs;
|
||||
__le32 rx_runt_errs;
|
||||
__le32 done_marker;
|
||||
};
|
||||
|
||||
enum Rx_ring_state_bits {
|
||||
|
@ -1139,7 +1133,7 @@ speedo_rx_soft_reset(struct net_device *dev)
|
|||
|
||||
rfd = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
|
||||
|
||||
rfd->rx_buf_addr = 0xffffffff;
|
||||
rfd->rx_buf_addr = cpu_to_le32(0xffffffff);
|
||||
|
||||
if (wait_for_cmd_done(dev, sp) != 0) {
|
||||
printk("%s: RxAbort command stalled\n", dev->name);
|
||||
|
@ -1275,7 +1269,7 @@ speedo_init_rx_ring(struct net_device *dev)
|
|||
rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */
|
||||
rxf->link = 0; /* None yet. */
|
||||
/* This field unused by i82557. */
|
||||
rxf->rx_buf_addr = 0xffffffff;
|
||||
rxf->rx_buf_addr = cpu_to_le32(0xffffffff);
|
||||
rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
|
||||
pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[i],
|
||||
sizeof(struct RxFD), PCI_DMA_TODEVICE);
|
||||
|
@ -1657,7 +1651,7 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
|
|||
PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
|
||||
skb->dev = dev;
|
||||
skb_reserve(skb, sizeof(struct RxFD));
|
||||
rxf->rx_buf_addr = 0xffffffff;
|
||||
rxf->rx_buf_addr = cpu_to_le32(0xffffffff);
|
||||
pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
|
||||
sizeof(struct RxFD), PCI_DMA_TODEVICE);
|
||||
return rxf;
|
||||
|
@ -1788,7 +1782,7 @@ speedo_rx(struct net_device *dev)
|
|||
/* Check if the packet is long enough to just accept without
|
||||
copying to a properly sized skbuff. */
|
||||
if (pkt_len < rx_copybreak
|
||||
&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
|
||||
&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
|
||||
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
||||
/* 'skb_put()' points to the start of sk_buff data area. */
|
||||
pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
|
||||
|
@ -1933,7 +1927,7 @@ speedo_get_stats(struct net_device *dev)
|
|||
void __iomem *ioaddr = sp->regs;
|
||||
|
||||
/* Update only if the previous dump finished. */
|
||||
if (sp->lstats->done_marker == le32_to_cpu(0xA007)) {
|
||||
if (sp->lstats->done_marker == cpu_to_le32(0xA007)) {
|
||||
sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats->tx_coll16_errs);
|
||||
sp->stats.tx_window_errors += le32_to_cpu(sp->lstats->tx_late_colls);
|
||||
sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_underruns);
|
||||
|
@ -2142,7 +2136,7 @@ static void set_rx_mode(struct net_device *dev)
|
|||
/* The simple case of 0-3 multicast list entries occurs often, and
|
||||
fits within one tx_ring[] entry. */
|
||||
struct dev_mc_list *mclist;
|
||||
u16 *setup_params, *eaddrs;
|
||||
__le16 *setup_params, *eaddrs;
|
||||
|
||||
spin_lock_irqsave(&sp->lock, flags);
|
||||
entry = sp->cur_tx++ % TX_RING_SIZE;
|
||||
|
@ -2154,12 +2148,12 @@ static void set_rx_mode(struct net_device *dev)
|
|||
sp->tx_ring[entry].link =
|
||||
cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
|
||||
sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
|
||||
setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr;
|
||||
setup_params = (__le16 *)&sp->tx_ring[entry].tx_desc_addr;
|
||||
*setup_params++ = cpu_to_le16(dev->mc_count*6);
|
||||
/* Fill in the multicast addresses. */
|
||||
for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
|
||||
i++, mclist = mclist->next) {
|
||||
eaddrs = (u16 *)mclist->dmi_addr;
|
||||
eaddrs = (__le16 *)mclist->dmi_addr;
|
||||
*setup_params++ = *eaddrs++;
|
||||
*setup_params++ = *eaddrs++;
|
||||
*setup_params++ = *eaddrs++;
|
||||
|
@ -2177,7 +2171,7 @@ static void set_rx_mode(struct net_device *dev)
|
|||
spin_unlock_irqrestore(&sp->lock, flags);
|
||||
} else if (new_rx_mode == 0) {
|
||||
struct dev_mc_list *mclist;
|
||||
u16 *setup_params, *eaddrs;
|
||||
__le16 *setup_params, *eaddrs;
|
||||
struct speedo_mc_block *mc_blk;
|
||||
struct descriptor *mc_setup_frm;
|
||||
int i;
|
||||
|
@ -2204,12 +2198,12 @@ static void set_rx_mode(struct net_device *dev)
|
|||
mc_setup_frm->cmd_status =
|
||||
cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList);
|
||||
/* Link set below. */
|
||||
setup_params = (u16 *)&mc_setup_frm->params;
|
||||
setup_params = (__le16 *)&mc_setup_frm->params;
|
||||
*setup_params++ = cpu_to_le16(dev->mc_count*6);
|
||||
/* Fill in the multicast addresses. */
|
||||
for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
|
||||
i++, mclist = mclist->next) {
|
||||
eaddrs = (u16 *)mclist->dmi_addr;
|
||||
eaddrs = (__le16 *)mclist->dmi_addr;
|
||||
*setup_params++ = *eaddrs++;
|
||||
*setup_params++ = *eaddrs++;
|
||||
*setup_params++ = *eaddrs++;
|
||||
|
|
|
@ -456,8 +456,9 @@ static int eexp_open(struct net_device *dev)
|
|||
if (!dev->irq || !irqrmap[dev->irq])
|
||||
return -ENXIO;
|
||||
|
||||
ret = request_irq(dev->irq,&eexp_irq,0,dev->name,dev);
|
||||
if (ret) return ret;
|
||||
ret = request_irq(dev->irq, &eexp_irq, 0, dev->name, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) {
|
||||
printk(KERN_WARNING "EtherExpress io port %x, is busy.\n"
|
||||
|
@ -768,7 +769,7 @@ static void eexp_cmd_clear(struct net_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static irqreturn_t eexp_irq(int irq, void *dev_info)
|
||||
static irqreturn_t eexp_irq(int dummy, void *dev_info)
|
||||
{
|
||||
struct net_device *dev = dev_info;
|
||||
struct net_local *lp;
|
||||
|
@ -783,8 +784,7 @@ static irqreturn_t eexp_irq(int irq, void *dev_info)
|
|||
old_read_ptr = inw(ioaddr+READ_PTR);
|
||||
old_write_ptr = inw(ioaddr+WRITE_PTR);
|
||||
|
||||
outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
|
||||
|
||||
outb(SIRQ_dis|irqrmap[dev->irq], ioaddr+SET_IRQ);
|
||||
|
||||
status = scb_status(dev);
|
||||
|
||||
|
@ -851,7 +851,7 @@ static irqreturn_t eexp_irq(int irq, void *dev_info)
|
|||
|
||||
eexp_cmd_clear(dev);
|
||||
|
||||
outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ);
|
||||
outb(SIRQ_en|irqrmap[dev->irq], ioaddr+SET_IRQ);
|
||||
|
||||
#if NET_DEBUG > 6
|
||||
printk("%s: leaving eexp_irq()\n", dev->name);
|
||||
|
|
1600
drivers/net/enc28j60.c
Normal file
1600
drivers/net/enc28j60.c
Normal file
File diff suppressed because it is too large
Load diff
309
drivers/net/enc28j60_hw.h
Normal file
309
drivers/net/enc28j60_hw.h
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* enc28j60_hw.h: EDTP FrameThrower style enc28j60 registers
|
||||
*
|
||||
* $Id: enc28j60_hw.h,v 1.9 2007/12/14 11:59:16 claudio Exp $
|
||||
*/
|
||||
|
||||
#ifndef _ENC28J60_HW_H
|
||||
#define _ENC28J60_HW_H
|
||||
|
||||
/*
|
||||
* ENC28J60 Control Registers
|
||||
* Control register definitions are a combination of address,
|
||||
* bank number, and Ethernet/MAC/PHY indicator bits.
|
||||
* - Register address (bits 0-4)
|
||||
* - Bank number (bits 5-6)
|
||||
* - MAC/MII indicator (bit 7)
|
||||
*/
|
||||
#define ADDR_MASK 0x1F
|
||||
#define BANK_MASK 0x60
|
||||
#define SPRD_MASK 0x80
|
||||
/* All-bank registers */
|
||||
#define EIE 0x1B
|
||||
#define EIR 0x1C
|
||||
#define ESTAT 0x1D
|
||||
#define ECON2 0x1E
|
||||
#define ECON1 0x1F
|
||||
/* Bank 0 registers */
|
||||
#define ERDPTL (0x00|0x00)
|
||||
#define ERDPTH (0x01|0x00)
|
||||
#define EWRPTL (0x02|0x00)
|
||||
#define EWRPTH (0x03|0x00)
|
||||
#define ETXSTL (0x04|0x00)
|
||||
#define ETXSTH (0x05|0x00)
|
||||
#define ETXNDL (0x06|0x00)
|
||||
#define ETXNDH (0x07|0x00)
|
||||
#define ERXSTL (0x08|0x00)
|
||||
#define ERXSTH (0x09|0x00)
|
||||
#define ERXNDL (0x0A|0x00)
|
||||
#define ERXNDH (0x0B|0x00)
|
||||
#define ERXRDPTL (0x0C|0x00)
|
||||
#define ERXRDPTH (0x0D|0x00)
|
||||
#define ERXWRPTL (0x0E|0x00)
|
||||
#define ERXWRPTH (0x0F|0x00)
|
||||
#define EDMASTL (0x10|0x00)
|
||||
#define EDMASTH (0x11|0x00)
|
||||
#define EDMANDL (0x12|0x00)
|
||||
#define EDMANDH (0x13|0x00)
|
||||
#define EDMADSTL (0x14|0x00)
|
||||
#define EDMADSTH (0x15|0x00)
|
||||
#define EDMACSL (0x16|0x00)
|
||||
#define EDMACSH (0x17|0x00)
|
||||
/* Bank 1 registers */
|
||||
#define EHT0 (0x00|0x20)
|
||||
#define EHT1 (0x01|0x20)
|
||||
#define EHT2 (0x02|0x20)
|
||||
#define EHT3 (0x03|0x20)
|
||||
#define EHT4 (0x04|0x20)
|
||||
#define EHT5 (0x05|0x20)
|
||||
#define EHT6 (0x06|0x20)
|
||||
#define EHT7 (0x07|0x20)
|
||||
#define EPMM0 (0x08|0x20)
|
||||
#define EPMM1 (0x09|0x20)
|
||||
#define EPMM2 (0x0A|0x20)
|
||||
#define EPMM3 (0x0B|0x20)
|
||||
#define EPMM4 (0x0C|0x20)
|
||||
#define EPMM5 (0x0D|0x20)
|
||||
#define EPMM6 (0x0E|0x20)
|
||||
#define EPMM7 (0x0F|0x20)
|
||||
#define EPMCSL (0x10|0x20)
|
||||
#define EPMCSH (0x11|0x20)
|
||||
#define EPMOL (0x14|0x20)
|
||||
#define EPMOH (0x15|0x20)
|
||||
#define EWOLIE (0x16|0x20)
|
||||
#define EWOLIR (0x17|0x20)
|
||||
#define ERXFCON (0x18|0x20)
|
||||
#define EPKTCNT (0x19|0x20)
|
||||
/* Bank 2 registers */
|
||||
#define MACON1 (0x00|0x40|SPRD_MASK)
|
||||
/* #define MACON2 (0x01|0x40|SPRD_MASK) */
|
||||
#define MACON3 (0x02|0x40|SPRD_MASK)
|
||||
#define MACON4 (0x03|0x40|SPRD_MASK)
|
||||
#define MABBIPG (0x04|0x40|SPRD_MASK)
|
||||
#define MAIPGL (0x06|0x40|SPRD_MASK)
|
||||
#define MAIPGH (0x07|0x40|SPRD_MASK)
|
||||
#define MACLCON1 (0x08|0x40|SPRD_MASK)
|
||||
#define MACLCON2 (0x09|0x40|SPRD_MASK)
|
||||
#define MAMXFLL (0x0A|0x40|SPRD_MASK)
|
||||
#define MAMXFLH (0x0B|0x40|SPRD_MASK)
|
||||
#define MAPHSUP (0x0D|0x40|SPRD_MASK)
|
||||
#define MICON (0x11|0x40|SPRD_MASK)
|
||||
#define MICMD (0x12|0x40|SPRD_MASK)
|
||||
#define MIREGADR (0x14|0x40|SPRD_MASK)
|
||||
#define MIWRL (0x16|0x40|SPRD_MASK)
|
||||
#define MIWRH (0x17|0x40|SPRD_MASK)
|
||||
#define MIRDL (0x18|0x40|SPRD_MASK)
|
||||
#define MIRDH (0x19|0x40|SPRD_MASK)
|
||||
/* Bank 3 registers */
|
||||
#define MAADR1 (0x00|0x60|SPRD_MASK)
|
||||
#define MAADR0 (0x01|0x60|SPRD_MASK)
|
||||
#define MAADR3 (0x02|0x60|SPRD_MASK)
|
||||
#define MAADR2 (0x03|0x60|SPRD_MASK)
|
||||
#define MAADR5 (0x04|0x60|SPRD_MASK)
|
||||
#define MAADR4 (0x05|0x60|SPRD_MASK)
|
||||
#define EBSTSD (0x06|0x60)
|
||||
#define EBSTCON (0x07|0x60)
|
||||
#define EBSTCSL (0x08|0x60)
|
||||
#define EBSTCSH (0x09|0x60)
|
||||
#define MISTAT (0x0A|0x60|SPRD_MASK)
|
||||
#define EREVID (0x12|0x60)
|
||||
#define ECOCON (0x15|0x60)
|
||||
#define EFLOCON (0x17|0x60)
|
||||
#define EPAUSL (0x18|0x60)
|
||||
#define EPAUSH (0x19|0x60)
|
||||
/* PHY registers */
|
||||
#define PHCON1 0x00
|
||||
#define PHSTAT1 0x01
|
||||
#define PHHID1 0x02
|
||||
#define PHHID2 0x03
|
||||
#define PHCON2 0x10
|
||||
#define PHSTAT2 0x11
|
||||
#define PHIE 0x12
|
||||
#define PHIR 0x13
|
||||
#define PHLCON 0x14
|
||||
|
||||
/* ENC28J60 EIE Register Bit Definitions */
|
||||
#define EIE_INTIE 0x80
|
||||
#define EIE_PKTIE 0x40
|
||||
#define EIE_DMAIE 0x20
|
||||
#define EIE_LINKIE 0x10
|
||||
#define EIE_TXIE 0x08
|
||||
/* #define EIE_WOLIE 0x04 (reserved) */
|
||||
#define EIE_TXERIE 0x02
|
||||
#define EIE_RXERIE 0x01
|
||||
/* ENC28J60 EIR Register Bit Definitions */
|
||||
#define EIR_PKTIF 0x40
|
||||
#define EIR_DMAIF 0x20
|
||||
#define EIR_LINKIF 0x10
|
||||
#define EIR_TXIF 0x08
|
||||
/* #define EIR_WOLIF 0x04 (reserved) */
|
||||
#define EIR_TXERIF 0x02
|
||||
#define EIR_RXERIF 0x01
|
||||
/* ENC28J60 ESTAT Register Bit Definitions */
|
||||
#define ESTAT_INT 0x80
|
||||
#define ESTAT_LATECOL 0x10
|
||||
#define ESTAT_RXBUSY 0x04
|
||||
#define ESTAT_TXABRT 0x02
|
||||
#define ESTAT_CLKRDY 0x01
|
||||
/* ENC28J60 ECON2 Register Bit Definitions */
|
||||
#define ECON2_AUTOINC 0x80
|
||||
#define ECON2_PKTDEC 0x40
|
||||
#define ECON2_PWRSV 0x20
|
||||
#define ECON2_VRPS 0x08
|
||||
/* ENC28J60 ECON1 Register Bit Definitions */
|
||||
#define ECON1_TXRST 0x80
|
||||
#define ECON1_RXRST 0x40
|
||||
#define ECON1_DMAST 0x20
|
||||
#define ECON1_CSUMEN 0x10
|
||||
#define ECON1_TXRTS 0x08
|
||||
#define ECON1_RXEN 0x04
|
||||
#define ECON1_BSEL1 0x02
|
||||
#define ECON1_BSEL0 0x01
|
||||
/* ENC28J60 MACON1 Register Bit Definitions */
|
||||
#define MACON1_LOOPBK 0x10
|
||||
#define MACON1_TXPAUS 0x08
|
||||
#define MACON1_RXPAUS 0x04
|
||||
#define MACON1_PASSALL 0x02
|
||||
#define MACON1_MARXEN 0x01
|
||||
/* ENC28J60 MACON2 Register Bit Definitions */
|
||||
#define MACON2_MARST 0x80
|
||||
#define MACON2_RNDRST 0x40
|
||||
#define MACON2_MARXRST 0x08
|
||||
#define MACON2_RFUNRST 0x04
|
||||
#define MACON2_MATXRST 0x02
|
||||
#define MACON2_TFUNRST 0x01
|
||||
/* ENC28J60 MACON3 Register Bit Definitions */
|
||||
#define MACON3_PADCFG2 0x80
|
||||
#define MACON3_PADCFG1 0x40
|
||||
#define MACON3_PADCFG0 0x20
|
||||
#define MACON3_TXCRCEN 0x10
|
||||
#define MACON3_PHDRLEN 0x08
|
||||
#define MACON3_HFRMLEN 0x04
|
||||
#define MACON3_FRMLNEN 0x02
|
||||
#define MACON3_FULDPX 0x01
|
||||
/* ENC28J60 MICMD Register Bit Definitions */
|
||||
#define MICMD_MIISCAN 0x02
|
||||
#define MICMD_MIIRD 0x01
|
||||
/* ENC28J60 MISTAT Register Bit Definitions */
|
||||
#define MISTAT_NVALID 0x04
|
||||
#define MISTAT_SCAN 0x02
|
||||
#define MISTAT_BUSY 0x01
|
||||
/* ENC28J60 ERXFCON Register Bit Definitions */
|
||||
#define ERXFCON_UCEN 0x80
|
||||
#define ERXFCON_ANDOR 0x40
|
||||
#define ERXFCON_CRCEN 0x20
|
||||
#define ERXFCON_PMEN 0x10
|
||||
#define ERXFCON_MPEN 0x08
|
||||
#define ERXFCON_HTEN 0x04
|
||||
#define ERXFCON_MCEN 0x02
|
||||
#define ERXFCON_BCEN 0x01
|
||||
|
||||
/* ENC28J60 PHY PHCON1 Register Bit Definitions */
|
||||
#define PHCON1_PRST 0x8000
|
||||
#define PHCON1_PLOOPBK 0x4000
|
||||
#define PHCON1_PPWRSV 0x0800
|
||||
#define PHCON1_PDPXMD 0x0100
|
||||
/* ENC28J60 PHY PHSTAT1 Register Bit Definitions */
|
||||
#define PHSTAT1_PFDPX 0x1000
|
||||
#define PHSTAT1_PHDPX 0x0800
|
||||
#define PHSTAT1_LLSTAT 0x0004
|
||||
#define PHSTAT1_JBSTAT 0x0002
|
||||
/* ENC28J60 PHY PHSTAT2 Register Bit Definitions */
|
||||
#define PHSTAT2_TXSTAT (1 << 13)
|
||||
#define PHSTAT2_RXSTAT (1 << 12)
|
||||
#define PHSTAT2_COLSTAT (1 << 11)
|
||||
#define PHSTAT2_LSTAT (1 << 10)
|
||||
#define PHSTAT2_DPXSTAT (1 << 9)
|
||||
#define PHSTAT2_PLRITY (1 << 5)
|
||||
/* ENC28J60 PHY PHCON2 Register Bit Definitions */
|
||||
#define PHCON2_FRCLINK 0x4000
|
||||
#define PHCON2_TXDIS 0x2000
|
||||
#define PHCON2_JABBER 0x0400
|
||||
#define PHCON2_HDLDIS 0x0100
|
||||
/* ENC28J60 PHY PHIE Register Bit Definitions */
|
||||
#define PHIE_PLNKIE (1 << 4)
|
||||
#define PHIE_PGEIE (1 << 1)
|
||||
/* ENC28J60 PHY PHIR Register Bit Definitions */
|
||||
#define PHIR_PLNKIF (1 << 4)
|
||||
#define PHIR_PGEIF (1 << 1)
|
||||
|
||||
/* ENC28J60 Packet Control Byte Bit Definitions */
|
||||
#define PKTCTRL_PHUGEEN 0x08
|
||||
#define PKTCTRL_PPADEN 0x04
|
||||
#define PKTCTRL_PCRCEN 0x02
|
||||
#define PKTCTRL_POVERRIDE 0x01
|
||||
|
||||
/* ENC28J60 Transmit Status Vector */
|
||||
#define TSV_TXBYTECNT 0
|
||||
#define TSV_TXCOLLISIONCNT 16
|
||||
#define TSV_TXCRCERROR 20
|
||||
#define TSV_TXLENCHKERROR 21
|
||||
#define TSV_TXLENOUTOFRANGE 22
|
||||
#define TSV_TXDONE 23
|
||||
#define TSV_TXMULTICAST 24
|
||||
#define TSV_TXBROADCAST 25
|
||||
#define TSV_TXPACKETDEFER 26
|
||||
#define TSV_TXEXDEFER 27
|
||||
#define TSV_TXEXCOLLISION 28
|
||||
#define TSV_TXLATECOLLISION 29
|
||||
#define TSV_TXGIANT 30
|
||||
#define TSV_TXUNDERRUN 31
|
||||
#define TSV_TOTBYTETXONWIRE 32
|
||||
#define TSV_TXCONTROLFRAME 48
|
||||
#define TSV_TXPAUSEFRAME 49
|
||||
#define TSV_BACKPRESSUREAPP 50
|
||||
#define TSV_TXVLANTAGFRAME 51
|
||||
|
||||
#define TSV_SIZE 7
|
||||
#define TSV_BYTEOF(x) ((x) / 8)
|
||||
#define TSV_BITMASK(x) (1 << ((x) % 8))
|
||||
#define TSV_GETBIT(x, y) (((x)[TSV_BYTEOF(y)] & TSV_BITMASK(y)) ? 1 : 0)
|
||||
|
||||
/* ENC28J60 Receive Status Vector */
|
||||
#define RSV_RXLONGEVDROPEV 16
|
||||
#define RSV_CARRIEREV 18
|
||||
#define RSV_CRCERROR 20
|
||||
#define RSV_LENCHECKERR 21
|
||||
#define RSV_LENOUTOFRANGE 22
|
||||
#define RSV_RXOK 23
|
||||
#define RSV_RXMULTICAST 24
|
||||
#define RSV_RXBROADCAST 25
|
||||
#define RSV_DRIBBLENIBBLE 26
|
||||
#define RSV_RXCONTROLFRAME 27
|
||||
#define RSV_RXPAUSEFRAME 28
|
||||
#define RSV_RXUNKNOWNOPCODE 29
|
||||
#define RSV_RXTYPEVLAN 30
|
||||
|
||||
#define RSV_SIZE 6
|
||||
#define RSV_BITMASK(x) (1 << ((x) - 16))
|
||||
#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0)
|
||||
|
||||
|
||||
/* SPI operation codes */
|
||||
#define ENC28J60_READ_CTRL_REG 0x00
|
||||
#define ENC28J60_READ_BUF_MEM 0x3A
|
||||
#define ENC28J60_WRITE_CTRL_REG 0x40
|
||||
#define ENC28J60_WRITE_BUF_MEM 0x7A
|
||||
#define ENC28J60_BIT_FIELD_SET 0x80
|
||||
#define ENC28J60_BIT_FIELD_CLR 0xA0
|
||||
#define ENC28J60_SOFT_RESET 0xFF
|
||||
|
||||
|
||||
/* buffer boundaries applied to internal 8K ram
|
||||
* entire available packet buffer space is allocated.
|
||||
* Give TX buffer space for one full ethernet frame (~1500 bytes)
|
||||
* receive buffer gets the rest */
|
||||
#define TXSTART_INIT 0x1A00
|
||||
#define TXEND_INIT 0x1FFF
|
||||
|
||||
/* Put RX buffer at 0 as suggested by the Errata datasheet */
|
||||
#define RXSTART_INIT 0x0000
|
||||
#define RXEND_INIT 0x19FF
|
||||
|
||||
/* maximum ethernet frame length */
|
||||
#define MAX_FRAMELEN 1518
|
||||
|
||||
/* Prefered half duplex: LEDA: Link status LEDB: Rx/Tx activity */
|
||||
#define ENC28J60_LAMPS_MODE 0x3476
|
||||
|
||||
#endif
|
|
@ -712,8 +712,8 @@ static const struct nv_ethtool_str nv_etests_str[] = {
|
|||
};
|
||||
|
||||
struct register_test {
|
||||
__le32 reg;
|
||||
__le32 mask;
|
||||
__u32 reg;
|
||||
__u32 mask;
|
||||
};
|
||||
|
||||
static const struct register_test nv_registers_test[] = {
|
||||
|
@ -929,6 +929,16 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
|
|||
#define NV_SETUP_RX_RING 0x01
|
||||
#define NV_SETUP_TX_RING 0x02
|
||||
|
||||
static inline u32 dma_low(dma_addr_t addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline u32 dma_high(dma_addr_t addr)
|
||||
{
|
||||
return addr>>31>>1; /* 0 if 32bit, shift down by 32 if 64bit */
|
||||
}
|
||||
|
||||
static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
|
||||
{
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
|
@ -936,19 +946,19 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
|
|||
|
||||
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
|
||||
if (rxtx_flags & NV_SETUP_RX_RING) {
|
||||
writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
|
||||
writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
|
||||
}
|
||||
if (rxtx_flags & NV_SETUP_TX_RING) {
|
||||
writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
|
||||
writel(dma_low(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
|
||||
}
|
||||
} else {
|
||||
if (rxtx_flags & NV_SETUP_RX_RING) {
|
||||
writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
|
||||
writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh);
|
||||
writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
|
||||
writel(dma_high(np->ring_addr), base + NvRegRxRingPhysAddrHigh);
|
||||
}
|
||||
if (rxtx_flags & NV_SETUP_TX_RING) {
|
||||
writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
|
||||
writel((u32) (cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
|
||||
writel(dma_low(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
|
||||
writel(dma_high(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddrHigh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1571,8 +1581,8 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
|
|||
skb_tailroom(skb),
|
||||
PCI_DMA_FROMDEVICE);
|
||||
np->put_rx_ctx->dma_len = skb_tailroom(skb);
|
||||
np->put_rx.ex->bufhigh = cpu_to_le64(np->put_rx_ctx->dma) >> 32;
|
||||
np->put_rx.ex->buflow = cpu_to_le64(np->put_rx_ctx->dma) & 0x0FFFFFFFF;
|
||||
np->put_rx.ex->bufhigh = cpu_to_le32(dma_high(np->put_rx_ctx->dma));
|
||||
np->put_rx.ex->buflow = cpu_to_le32(dma_low(np->put_rx_ctx->dma));
|
||||
wmb();
|
||||
np->put_rx.ex->flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
|
||||
if (unlikely(np->put_rx.ex++ == np->last_rx.ex))
|
||||
|
@ -1937,8 +1947,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
|
|||
np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
|
||||
PCI_DMA_TODEVICE);
|
||||
np->put_tx_ctx->dma_len = bcnt;
|
||||
put_tx->bufhigh = cpu_to_le64(np->put_tx_ctx->dma) >> 32;
|
||||
put_tx->buflow = cpu_to_le64(np->put_tx_ctx->dma) & 0x0FFFFFFFF;
|
||||
put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
|
||||
put_tx->buflow = cpu_to_le32(dma_low(np->put_tx_ctx->dma));
|
||||
put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
|
||||
|
||||
tx_flags = NV_TX2_VALID;
|
||||
|
@ -1963,8 +1973,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
|
|||
np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
|
||||
PCI_DMA_TODEVICE);
|
||||
np->put_tx_ctx->dma_len = bcnt;
|
||||
put_tx->bufhigh = cpu_to_le64(np->put_tx_ctx->dma) >> 32;
|
||||
put_tx->buflow = cpu_to_le64(np->put_tx_ctx->dma) & 0x0FFFFFFFF;
|
||||
put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
|
||||
put_tx->buflow = cpu_to_le32(dma_low(np->put_tx_ctx->dma));
|
||||
put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
|
||||
|
||||
offset += bcnt;
|
||||
|
@ -2680,8 +2690,8 @@ static void nv_set_multicast(struct net_device *dev)
|
|||
walk = dev->mc_list;
|
||||
while (walk != NULL) {
|
||||
u32 a, b;
|
||||
a = le32_to_cpu(*(u32 *) walk->dmi_addr);
|
||||
b = le16_to_cpu(*(u16 *) (&walk->dmi_addr[4]));
|
||||
a = le32_to_cpu(*(__le32 *) walk->dmi_addr);
|
||||
b = le16_to_cpu(*(__le16 *) (&walk->dmi_addr[4]));
|
||||
alwaysOn[0] &= a;
|
||||
alwaysOff[0] &= ~a;
|
||||
alwaysOn[1] &= b;
|
||||
|
@ -4539,8 +4549,8 @@ static int nv_loopback_test(struct net_device *dev)
|
|||
np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
|
||||
np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
|
||||
} else {
|
||||
np->tx_ring.ex[0].bufhigh = cpu_to_le64(test_dma_addr) >> 32;
|
||||
np->tx_ring.ex[0].buflow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
|
||||
np->tx_ring.ex[0].bufhigh = cpu_to_le32(dma_high(test_dma_addr));
|
||||
np->tx_ring.ex[0].buflow = cpu_to_le32(dma_low(test_dma_addr));
|
||||
np->tx_ring.ex[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
|
||||
}
|
||||
writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
|
||||
|
|
|
@ -37,24 +37,6 @@
|
|||
|
||||
#include "gianfar.h"
|
||||
|
||||
#define GFAR_ATTR(_name) \
|
||||
static ssize_t gfar_show_##_name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf); \
|
||||
static ssize_t gfar_set_##_name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count); \
|
||||
static DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
|
||||
|
||||
#define GFAR_CREATE_FILE(_dev, _name) \
|
||||
device_create_file(&_dev->dev, &dev_attr_##_name)
|
||||
|
||||
GFAR_ATTR(bd_stash);
|
||||
GFAR_ATTR(rx_stash_size);
|
||||
GFAR_ATTR(rx_stash_index);
|
||||
GFAR_ATTR(fifo_threshold);
|
||||
GFAR_ATTR(fifo_starve);
|
||||
GFAR_ATTR(fifo_starve_off);
|
||||
|
||||
static ssize_t gfar_show_bd_stash(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -100,6 +82,8 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
|
||||
|
||||
static ssize_t gfar_show_rx_stash_size(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -146,6 +130,9 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
|
||||
gfar_set_rx_stash_size);
|
||||
|
||||
/* Stashing will only be enabled when rx_stash_size != 0 */
|
||||
static ssize_t gfar_show_rx_stash_index(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -184,6 +171,9 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
|
||||
gfar_set_rx_stash_index);
|
||||
|
||||
static ssize_t gfar_show_fifo_threshold(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
@ -219,6 +209,9 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
|
||||
gfar_set_fifo_threshold);
|
||||
|
||||
static ssize_t gfar_show_fifo_starve(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -253,6 +246,8 @@ static ssize_t gfar_set_fifo_starve(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, gfar_set_fifo_starve);
|
||||
|
||||
static ssize_t gfar_show_fifo_starve_off(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
@ -288,9 +283,13 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
|
||||
gfar_set_fifo_starve_off);
|
||||
|
||||
void gfar_init_sysfs(struct net_device *dev)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
int rc;
|
||||
|
||||
/* Initialize the default values */
|
||||
priv->rx_stash_size = DEFAULT_STASH_LENGTH;
|
||||
|
@ -301,11 +300,12 @@ void gfar_init_sysfs(struct net_device *dev)
|
|||
priv->bd_stash_en = DEFAULT_BD_STASH;
|
||||
|
||||
/* Create our sysfs files */
|
||||
GFAR_CREATE_FILE(dev, bd_stash);
|
||||
GFAR_CREATE_FILE(dev, rx_stash_size);
|
||||
GFAR_CREATE_FILE(dev, rx_stash_index);
|
||||
GFAR_CREATE_FILE(dev, fifo_threshold);
|
||||
GFAR_CREATE_FILE(dev, fifo_starve);
|
||||
GFAR_CREATE_FILE(dev, fifo_starve_off);
|
||||
|
||||
rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
|
||||
rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size);
|
||||
rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index);
|
||||
rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold);
|
||||
rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve);
|
||||
rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off);
|
||||
if (rc)
|
||||
dev_err(&dev->dev, "Error creating gianfar sysfs files.\n");
|
||||
}
|
||||
|
|
|
@ -701,7 +701,7 @@ static void sixpack_close(struct tty_struct *tty)
|
|||
sp = tty->disc_data;
|
||||
tty->disc_data = NULL;
|
||||
write_unlock(&disc_data_lock);
|
||||
if (sp == 0)
|
||||
if (!sp)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
|
|
@ -821,7 +821,7 @@ static void mkiss_close(struct tty_struct *tty)
|
|||
tty->disc_data = NULL;
|
||||
write_unlock(&disc_data_lock);
|
||||
|
||||
if (ax == 0)
|
||||
if (!ax)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
|
|
@ -201,7 +201,6 @@ static void z8530_init(void);
|
|||
|
||||
static void init_channel(struct scc_channel *scc);
|
||||
static void scc_key_trx (struct scc_channel *scc, char tx);
|
||||
static irqreturn_t scc_isr(int irq, void *dev_id);
|
||||
static void scc_init_timer(struct scc_channel *scc);
|
||||
|
||||
static int scc_net_alloc(const char *name, struct scc_channel *scc);
|
||||
|
@ -629,6 +628,7 @@ static void scc_isr_dispatch(struct scc_channel *scc, int vector)
|
|||
|
||||
static irqreturn_t scc_isr(int irq, void *dev_id)
|
||||
{
|
||||
int chip_irq = (long) dev_id;
|
||||
unsigned char vector;
|
||||
struct scc_channel *scc;
|
||||
struct scc_ctrl *ctrl;
|
||||
|
@ -665,7 +665,7 @@ static irqreturn_t scc_isr(int irq, void *dev_id)
|
|||
ctrl = SCC_ctrl;
|
||||
while (ctrl->chan_A)
|
||||
{
|
||||
if (ctrl->irq != irq)
|
||||
if (ctrl->irq != chip_irq)
|
||||
{
|
||||
ctrl++;
|
||||
continue;
|
||||
|
@ -1732,7 +1732,9 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|||
|
||||
if (!Ivec[hwcfg.irq].used && hwcfg.irq)
|
||||
{
|
||||
if (request_irq(hwcfg.irq, scc_isr, IRQF_DISABLED, "AX.25 SCC", NULL))
|
||||
if (request_irq(hwcfg.irq, scc_isr,
|
||||
IRQF_DISABLED, "AX.25 SCC",
|
||||
(void *)(long) hwcfg.irq))
|
||||
printk(KERN_WARNING "z8530drv: warning, cannot get IRQ %d\n", hwcfg.irq);
|
||||
else
|
||||
Ivec[hwcfg.irq].used = 1;
|
||||
|
|
|
@ -1153,7 +1153,7 @@ static void hp100_init_pdls(struct net_device *dev)
|
|||
printk("hp100: %s: init pdls\n", dev->name);
|
||||
#endif
|
||||
|
||||
if (0 == lp->page_vaddr_algn)
|
||||
if (!lp->page_vaddr_algn)
|
||||
printk("hp100: %s: Warning: lp->page_vaddr_algn not initialised!\n", dev->name);
|
||||
else {
|
||||
/* pageptr shall point into the DMA accessible memory region */
|
||||
|
|
|
@ -1297,7 +1297,6 @@ static int emac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
return emac_xmit_finish(dev, len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_TAH
|
||||
static inline int emac_xmit_split(struct emac_instance *dev, int slot,
|
||||
u32 pd, int len, int last, u16 base_ctrl)
|
||||
{
|
||||
|
@ -1410,9 +1409,6 @@ static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
|
|||
DBG2(dev, "stopped TX queue" NL);
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
# define emac_start_xmit_sg emac_start_xmit
|
||||
#endif /* !defined(CONFIG_IBM_NEW_EMAC_TAH) */
|
||||
|
||||
/* Tx lock BHs */
|
||||
static void emac_parse_tx_error(struct emac_instance *dev, u16 ctrl)
|
||||
|
@ -2683,13 +2679,8 @@ static int __devinit emac_probe(struct of_device *ofdev,
|
|||
|
||||
/* Fill in the driver function table */
|
||||
ndev->open = &emac_open;
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_TAH
|
||||
if (dev->tah_dev) {
|
||||
ndev->hard_start_xmit = &emac_start_xmit_sg;
|
||||
if (dev->tah_dev)
|
||||
ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
|
||||
} else
|
||||
#endif
|
||||
ndev->hard_start_xmit = &emac_start_xmit;
|
||||
ndev->tx_timeout = &emac_tx_timeout;
|
||||
ndev->watchdog_timeo = 5 * HZ;
|
||||
ndev->stop = &emac_close;
|
||||
|
@ -2697,8 +2688,11 @@ static int __devinit emac_probe(struct of_device *ofdev,
|
|||
ndev->set_multicast_list = &emac_set_multicast_list;
|
||||
ndev->do_ioctl = &emac_ioctl;
|
||||
if (emac_phy_supports_gige(dev->phy_mode)) {
|
||||
ndev->hard_start_xmit = &emac_start_xmit_sg;
|
||||
ndev->change_mtu = &emac_change_mtu;
|
||||
dev->commac.ops = &emac_commac_sg_ops;
|
||||
} else {
|
||||
ndev->hard_start_xmit = &emac_start_xmit;
|
||||
}
|
||||
SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ History:
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/mca-legacy.h>
|
||||
#include <linux/mca.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
@ -161,13 +161,13 @@ static void PrTime(void)
|
|||
|
||||
/* deduce resources out of POS registers */
|
||||
|
||||
static void getaddrs(int slot, int *base, int *memlen, int *iobase,
|
||||
int *irq, ibmlana_medium * medium)
|
||||
static void getaddrs(struct mca_device *mdev, int *base, int *memlen,
|
||||
int *iobase, int *irq, ibmlana_medium *medium)
|
||||
{
|
||||
u_char pos0, pos1;
|
||||
|
||||
pos0 = mca_read_stored_pos(slot, 2);
|
||||
pos1 = mca_read_stored_pos(slot, 3);
|
||||
pos0 = mca_device_read_stored_pos(mdev, 2);
|
||||
pos1 = mca_device_read_stored_pos(mdev, 3);
|
||||
|
||||
*base = 0xc0000 + ((pos1 & 0xf0) << 9);
|
||||
*memlen = (pos1 & 0x01) ? 0x8000 : 0x4000;
|
||||
|
@ -704,9 +704,9 @@ static void irqtxerr_handler(struct net_device *dev)
|
|||
|
||||
/* general interrupt entry */
|
||||
|
||||
static irqreturn_t irq_handler(int irq, void *device)
|
||||
static irqreturn_t irq_handler(int dummy, void *device)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) device;
|
||||
struct net_device *dev = device;
|
||||
u16 ival;
|
||||
|
||||
/* in case we're not meant... */
|
||||
|
@ -744,6 +744,7 @@ static irqreturn_t irq_handler(int irq, void *device)
|
|||
|
||||
/* MCA info */
|
||||
|
||||
#if 0 /* info available elsewhere, but this is kept for reference */
|
||||
static int ibmlana_getinfo(char *buf, int slot, void *d)
|
||||
{
|
||||
int len = 0, i;
|
||||
|
@ -771,6 +772,7 @@ static int ibmlana_getinfo(char *buf, int slot, void *d)
|
|||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* open driver. Means also initialization and start of LANCE */
|
||||
|
||||
|
@ -890,42 +892,52 @@ static void ibmlana_set_multicast_list(struct net_device *dev)
|
|||
* hardware check
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
static int ibmlana_irq;
|
||||
static int ibmlana_io;
|
||||
static int startslot; /* counts through slots when probing multiple devices */
|
||||
|
||||
static int ibmlana_probe(struct net_device *dev)
|
||||
static short ibmlana_adapter_ids[] __initdata = {
|
||||
IBM_LANA_ID,
|
||||
0x0000
|
||||
};
|
||||
|
||||
static char *ibmlana_adapter_names[] __initdata = {
|
||||
"IBM LAN Adapter/A",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int ibmlana_init_one(struct device *kdev)
|
||||
{
|
||||
int slot, z;
|
||||
struct mca_device *mdev = to_mca_device(kdev);
|
||||
struct net_device *dev;
|
||||
int slot = mdev->slot, z, rc;
|
||||
int base = 0, irq = 0, iobase = 0, memlen = 0;
|
||||
ibmlana_priv *priv;
|
||||
ibmlana_medium medium;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
/* can't work without an MCA bus ;-) */
|
||||
if (MCA_bus == 0)
|
||||
return -ENODEV;
|
||||
dev = alloc_etherdev(sizeof(ibmlana_priv));
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->irq = ibmlana_irq;
|
||||
dev->base_addr = ibmlana_io;
|
||||
|
||||
base = dev->mem_start;
|
||||
irq = dev->irq;
|
||||
|
||||
for (slot = startslot; (slot = mca_find_adapter(IBM_LANA_ID, slot)) != -1; slot++) {
|
||||
/* deduce card addresses */
|
||||
getaddrs(slot, &base, &memlen, &iobase, &irq, &medium);
|
||||
/* deduce card addresses */
|
||||
getaddrs(mdev, &base, &memlen, &iobase, &irq, &medium);
|
||||
|
||||
/* slot already in use ? */
|
||||
if (mca_is_adapter_used(slot))
|
||||
continue;
|
||||
/* were we looking for something different ? */
|
||||
if (dev->irq && dev->irq != irq)
|
||||
continue;
|
||||
if (dev->mem_start && dev->mem_start != base)
|
||||
continue;
|
||||
/* found something that matches */
|
||||
break;
|
||||
/* were we looking for something different ? */
|
||||
if (dev->irq && dev->irq != irq) {
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
if (dev->mem_start && dev->mem_start != base) {
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* nothing found ? */
|
||||
if (slot == -1)
|
||||
return (base != 0 || irq != 0) ? -ENXIO : -ENODEV;
|
||||
|
||||
/* announce success */
|
||||
printk(KERN_INFO "%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1);
|
||||
|
@ -934,16 +946,16 @@ static int ibmlana_probe(struct net_device *dev)
|
|||
if (!request_region(iobase, IBM_LANA_IORANGE, DRV_NAME)) {
|
||||
printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", DRV_NAME, iobase);
|
||||
startslot = slot + 1;
|
||||
return -EBUSY;
|
||||
rc = -EBUSY;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
priv->slot = slot;
|
||||
priv->realirq = irq;
|
||||
priv->realirq = mca_device_transform_irq(mdev, irq);
|
||||
priv->medium = medium;
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
|
||||
/* set base + irq for this device (irq not allocated so far) */
|
||||
|
||||
dev->irq = 0;
|
||||
|
@ -955,22 +967,18 @@ static int ibmlana_probe(struct net_device *dev)
|
|||
if (!priv->base) {
|
||||
printk(KERN_ERR "%s: cannot remap memory!\n", DRV_NAME);
|
||||
startslot = slot + 1;
|
||||
release_region(iobase, IBM_LANA_IORANGE);
|
||||
return -EBUSY;
|
||||
rc = -EBUSY;
|
||||
goto err_out_reg;
|
||||
}
|
||||
|
||||
/* make procfs entries */
|
||||
mca_set_adapter_name(slot, "IBM LAN Adapter/A");
|
||||
mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmlana_getinfo, dev);
|
||||
|
||||
mca_mark_as_used(slot);
|
||||
mca_device_set_name(mdev, ibmlana_adapter_names[mdev->index]);
|
||||
mca_device_set_claim(mdev, 1);
|
||||
|
||||
/* set methods */
|
||||
|
||||
dev->open = ibmlana_open;
|
||||
dev->stop = ibmlana_close;
|
||||
dev->hard_start_xmit = ibmlana_tx;
|
||||
dev->do_ioctl = NULL;
|
||||
dev->set_multicast_list = ibmlana_set_multicast_list;
|
||||
dev->flags |= IFF_MULTICAST;
|
||||
|
||||
|
@ -996,6 +1004,35 @@ static int ibmlana_probe(struct net_device *dev)
|
|||
|
||||
startslot = slot + 1;
|
||||
|
||||
rc = register_netdev(dev);
|
||||
if (rc)
|
||||
goto err_out_claimed;
|
||||
|
||||
dev_set_drvdata(kdev, dev);
|
||||
return 0;
|
||||
|
||||
err_out_claimed:
|
||||
mca_device_set_claim(mdev, 0);
|
||||
iounmap(priv->base);
|
||||
err_out_reg:
|
||||
release_region(iobase, IBM_LANA_IORANGE);
|
||||
err_out:
|
||||
free_netdev(dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ibmlana_remove_one(struct device *kdev)
|
||||
{
|
||||
struct mca_device *mdev = to_mca_device(kdev);
|
||||
struct net_device *dev = dev_get_drvdata(kdev);
|
||||
ibmlana_priv *priv = netdev_priv(dev);
|
||||
|
||||
unregister_netdev(dev);
|
||||
/*DeinitBoard(dev); */
|
||||
release_region(dev->base_addr, IBM_LANA_IORANGE);
|
||||
mca_device_set_claim(mdev, 0);
|
||||
iounmap(priv->base);
|
||||
free_netdev(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1003,66 +1040,31 @@ static int ibmlana_probe(struct net_device *dev)
|
|||
* modularization support
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
#define DEVMAX 5
|
||||
|
||||
static struct net_device *moddevs[DEVMAX];
|
||||
static int irq;
|
||||
static int io;
|
||||
|
||||
module_param(irq, int, 0);
|
||||
module_param(io, int, 0);
|
||||
module_param_named(irq, ibmlana_irq, int, 0);
|
||||
module_param_named(io, ibmlana_io, int, 0);
|
||||
MODULE_PARM_DESC(irq, "IBM LAN/A IRQ number");
|
||||
MODULE_PARM_DESC(io, "IBM LAN/A I/O base address");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int z;
|
||||
static struct mca_driver ibmlana_driver = {
|
||||
.id_table = ibmlana_adapter_ids,
|
||||
.driver = {
|
||||
.name = "ibmlana",
|
||||
.bus = &mca_bus_type,
|
||||
.probe = ibmlana_init_one,
|
||||
.remove = ibmlana_remove_one,
|
||||
},
|
||||
};
|
||||
|
||||
startslot = 0;
|
||||
for (z = 0; z < DEVMAX; z++) {
|
||||
struct net_device *dev = alloc_etherdev(sizeof(ibmlana_priv));
|
||||
if (!dev)
|
||||
break;
|
||||
dev->irq = irq;
|
||||
dev->base_addr = io;
|
||||
if (ibmlana_probe(dev)) {
|
||||
free_netdev(dev);
|
||||
break;
|
||||
}
|
||||
if (register_netdev(dev)) {
|
||||
ibmlana_priv *priv = netdev_priv(dev);
|
||||
release_region(dev->base_addr, IBM_LANA_IORANGE);
|
||||
mca_mark_as_unused(priv->slot);
|
||||
mca_set_adapter_name(priv->slot, "");
|
||||
mca_set_adapter_procfn(priv->slot, NULL, NULL);
|
||||
iounmap(priv->base);
|
||||
free_netdev(dev);
|
||||
break;
|
||||
}
|
||||
moddevs[z] = dev;
|
||||
}
|
||||
return (z > 0) ? 0 : -EIO;
|
||||
static int __init ibmlana_init_module(void)
|
||||
{
|
||||
return mca_register_driver(&ibmlana_driver);
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
static void __exit ibmlana_cleanup_module(void)
|
||||
{
|
||||
int z;
|
||||
for (z = 0; z < DEVMAX; z++) {
|
||||
struct net_device *dev = moddevs[z];
|
||||
if (dev) {
|
||||
ibmlana_priv *priv = netdev_priv(dev);
|
||||
unregister_netdev(dev);
|
||||
/*DeinitBoard(dev); */
|
||||
release_region(dev->base_addr, IBM_LANA_IORANGE);
|
||||
mca_mark_as_unused(priv->slot);
|
||||
mca_set_adapter_name(priv->slot, "");
|
||||
mca_set_adapter_procfn(priv->slot, NULL, NULL);
|
||||
iounmap(priv->base);
|
||||
free_netdev(dev);
|
||||
}
|
||||
}
|
||||
mca_unregister_driver(&ibmlana_driver);
|
||||
}
|
||||
#endif /* MODULE */
|
||||
|
||||
module_init(ibmlana_init_module);
|
||||
module_exit(ibmlana_cleanup_module);
|
||||
|
|
37
drivers/net/igb/Makefile
Normal file
37
drivers/net/igb/Makefile
Normal file
|
@ -0,0 +1,37 @@
|
|||
################################################################################
|
||||
#
|
||||
# Intel 82575 PCI-Express Ethernet Linux driver
|
||||
# Copyright(c) 1999 - 2007 Intel Corporation.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# The full GNU General Public License is included in this distribution in
|
||||
# the file called "COPYING".
|
||||
#
|
||||
# Contact Information:
|
||||
# Linux NICS <linux.nics@intel.com>
|
||||
# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
#
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Makefile for the Intel(R) 82575 PCI-Express ethernet driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IGB) += igb.o
|
||||
|
||||
igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
|
||||
e1000_mac.o e1000_nvm.o e1000_phy.o
|
||||
|
1269
drivers/net/igb/e1000_82575.c
Normal file
1269
drivers/net/igb/e1000_82575.c
Normal file
File diff suppressed because it is too large
Load diff
150
drivers/net/igb/e1000_82575.h
Normal file
150
drivers/net/igb/e1000_82575.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) Gigabit Ethernet Linux driver
|
||||
Copyright(c) 2007 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_82575_H_
|
||||
#define _E1000_82575_H_
|
||||
|
||||
#define E1000_RAR_ENTRIES_82575 16
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
|
||||
#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
|
||||
|
||||
#define E1000_EICR_TX_QUEUE ( \
|
||||
E1000_EICR_TX_QUEUE0 | \
|
||||
E1000_EICR_TX_QUEUE1 | \
|
||||
E1000_EICR_TX_QUEUE2 | \
|
||||
E1000_EICR_TX_QUEUE3)
|
||||
|
||||
#define E1000_EICR_RX_QUEUE ( \
|
||||
E1000_EICR_RX_QUEUE0 | \
|
||||
E1000_EICR_RX_QUEUE1 | \
|
||||
E1000_EICR_RX_QUEUE2 | \
|
||||
E1000_EICR_RX_QUEUE3)
|
||||
|
||||
#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE
|
||||
#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE
|
||||
|
||||
/* Immediate Interrupt RX (A.K.A. Low Latency Interrupt) */
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
u64 pkt_addr; /* Packet buffer address */
|
||||
u64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
u16 pkt_info; /* RSS type, Packet type */
|
||||
u16 hdr_info; /* Split Header,
|
||||
* header buffer length */
|
||||
} lo_dword;
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length; /* Packet length */
|
||||
u16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
|
||||
/* RSS Hash results */
|
||||
|
||||
/* RSS Packet Types as indicated in the receive descriptor */
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
u64 buffer_addr; /* Address of descriptor's data buf */
|
||||
u32 cmd_type_len;
|
||||
u32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
u64 rsvd; /* Reserved */
|
||||
u32 nxtseq_seed;
|
||||
u32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
u32 vlan_macip_lens;
|
||||
u32 seqnum_seed;
|
||||
u32 type_tucmd_mlhl;
|
||||
u32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
/* IPSec Encrypt Enable for ESP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
/* Adv ctxt IPSec SA IDX mask */
|
||||
/* Adv ctxt IPSec ESP len mask */
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
/* Tx Queue Arbitration Priority 0=low, 1=high */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
|
||||
|
||||
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* TX Desc writeback RO bit */
|
||||
|
||||
#endif
|
772
drivers/net/igb/e1000_defines.h
Normal file
772
drivers/net/igb/e1000_defines.h
Normal file
|
@ -0,0 +1,772 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) Gigabit Ethernet Linux driver
|
||||
Copyright(c) 2007 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_DEFINES_H_
|
||||
#define _E1000_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
/* Definitions for power management and wakeup registers */
|
||||
/* Wake Up Control */
|
||||
#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
|
||||
|
||||
/* Wake Up Filter Control */
|
||||
#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
|
||||
#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
|
||||
#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
|
||||
#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
|
||||
#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
|
||||
#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
|
||||
#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
|
||||
#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
|
||||
#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
|
||||
#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
|
||||
#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
|
||||
#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
|
||||
#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
|
||||
|
||||
/* Wake Up Status */
|
||||
|
||||
/* Wake Up Packet Length */
|
||||
|
||||
/* Four Flexible Filters are supported */
|
||||
#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
|
||||
|
||||
/* Each Flexible Filter is at most 128 (0x80) bytes in length */
|
||||
#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128
|
||||
|
||||
|
||||
/* Extended Device Control */
|
||||
#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */
|
||||
#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
|
||||
#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
|
||||
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
|
||||
#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */
|
||||
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
|
||||
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
|
||||
#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
|
||||
#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000
|
||||
#define E1000_CTRL_EXT_EIAME 0x01000000
|
||||
#define E1000_CTRL_EXT_IRCA 0x00000001
|
||||
/* Interrupt delay cancellation */
|
||||
/* Driver loaded bit for FW */
|
||||
#define E1000_CTRL_EXT_DRV_LOAD 0x10000000
|
||||
/* Interrupt acknowledge Auto-mask */
|
||||
/* Clear Interrupt timers after IMS clear */
|
||||
/* packet buffer parity error detection enabled */
|
||||
/* descriptor FIFO parity error detection enable */
|
||||
#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
|
||||
#define E1000_I2CCMD_REG_ADDR_SHIFT 16
|
||||
#define E1000_I2CCMD_PHY_ADDR_SHIFT 24
|
||||
#define E1000_I2CCMD_OPCODE_READ 0x08000000
|
||||
#define E1000_I2CCMD_OPCODE_WRITE 0x00000000
|
||||
#define E1000_I2CCMD_READY 0x20000000
|
||||
#define E1000_I2CCMD_ERROR 0x80000000
|
||||
#define E1000_MAX_SGMII_PHY_REG_ADDR 255
|
||||
#define E1000_I2CCMD_PHY_TIMEOUT 200
|
||||
|
||||
/* Receive Decriptor bit definitions */
|
||||
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */
|
||||
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */
|
||||
#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
|
||||
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
|
||||
#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
|
||||
#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */
|
||||
#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
|
||||
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
|
||||
|
||||
#define E1000_RXDEXT_STATERR_CE 0x01000000
|
||||
#define E1000_RXDEXT_STATERR_SE 0x02000000
|
||||
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
|
||||
#define E1000_RXDEXT_STATERR_CXE 0x10000000
|
||||
#define E1000_RXDEXT_STATERR_TCPE 0x20000000
|
||||
#define E1000_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define E1000_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
/* mask to determine if packets should be dropped due to frame errors */
|
||||
#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
|
||||
E1000_RXD_ERR_CE | \
|
||||
E1000_RXD_ERR_SE | \
|
||||
E1000_RXD_ERR_SEQ | \
|
||||
E1000_RXD_ERR_CXE | \
|
||||
E1000_RXD_ERR_RXE)
|
||||
|
||||
/* Same mask, but for extended and packet split descriptors */
|
||||
#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
|
||||
E1000_RXDEXT_STATERR_CE | \
|
||||
E1000_RXDEXT_STATERR_SE | \
|
||||
E1000_RXDEXT_STATERR_SEQ | \
|
||||
E1000_RXDEXT_STATERR_CXE | \
|
||||
E1000_RXDEXT_STATERR_RXE)
|
||||
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
|
||||
|
||||
|
||||
/* Management Control */
|
||||
#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
|
||||
#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
|
||||
#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
|
||||
/* Enable Neighbor Discovery Filtering */
|
||||
#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
|
||||
#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
|
||||
/* Enable MAC address filtering */
|
||||
#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000
|
||||
/* Enable MNG packets to host memory */
|
||||
#define E1000_MANC_EN_MNG2HOST 0x00200000
|
||||
/* Enable IP address filtering */
|
||||
|
||||
|
||||
/* Receive Control */
|
||||
#define E1000_RCTL_EN 0x00000002 /* enable */
|
||||
#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
|
||||
#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */
|
||||
#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */
|
||||
#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
|
||||
#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
|
||||
#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
|
||||
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
|
||||
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
|
||||
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
|
||||
#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
|
||||
/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
|
||||
#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
|
||||
#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
|
||||
#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
|
||||
#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
|
||||
/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
|
||||
#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
|
||||
#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
|
||||
#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
|
||||
#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
|
||||
#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
|
||||
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
|
||||
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
|
||||
/*
|
||||
* Use byte values for the following shift parameters
|
||||
* Usage:
|
||||
* psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
|
||||
* E1000_PSRCTL_BSIZE0_MASK) |
|
||||
* ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
|
||||
* E1000_PSRCTL_BSIZE1_MASK) |
|
||||
* ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
|
||||
* E1000_PSRCTL_BSIZE2_MASK) |
|
||||
* ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
|
||||
* E1000_PSRCTL_BSIZE3_MASK))
|
||||
* where value0 = [128..16256], default=256
|
||||
* value1 = [1024..64512], default=4096
|
||||
* value2 = [0..64512], default=4096
|
||||
* value3 = [0..64512], default=0
|
||||
*/
|
||||
|
||||
#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
|
||||
#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
|
||||
#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
|
||||
#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
|
||||
|
||||
#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
|
||||
#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
|
||||
#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
|
||||
#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
|
||||
|
||||
/* SWFW_SYNC Definitions */
|
||||
#define E1000_SWFW_EEP_SM 0x1
|
||||
#define E1000_SWFW_PHY0_SM 0x2
|
||||
#define E1000_SWFW_PHY1_SM 0x4
|
||||
|
||||
/* FACTPS Definitions */
|
||||
/* Device Control */
|
||||
#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
|
||||
#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
|
||||
#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
|
||||
#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
|
||||
#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
|
||||
#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
|
||||
#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
|
||||
#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
|
||||
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
/* Defined polarity of Dock/Undock indication in SDP[0] */
|
||||
/* Reset both PHY ports, through PHYRST_N pin */
|
||||
/* enable link status from external LINK_0 and LINK_1 pins */
|
||||
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
|
||||
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
|
||||
#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
|
||||
#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
|
||||
#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
|
||||
#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
|
||||
#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
|
||||
#define E1000_CTRL_RST 0x04000000 /* Global reset */
|
||||
#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
|
||||
#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
|
||||
#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
|
||||
#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
|
||||
/* Initiate an interrupt to manageability engine */
|
||||
#define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */
|
||||
|
||||
/* Bit definitions for the Management Data IO (MDIO) and Management Data
|
||||
* Clock (MDC) pins in the Device Control Register.
|
||||
*/
|
||||
|
||||
#define E1000_CONNSW_ENRGSRC 0x4
|
||||
#define E1000_PCS_LCTL_FLV_LINK_UP 1
|
||||
#define E1000_PCS_LCTL_FSV_100 2
|
||||
#define E1000_PCS_LCTL_FSV_1000 4
|
||||
#define E1000_PCS_LCTL_FDV_FULL 8
|
||||
#define E1000_PCS_LCTL_FSD 0x10
|
||||
#define E1000_PCS_LCTL_FORCE_LINK 0x20
|
||||
#define E1000_PCS_LCTL_AN_ENABLE 0x10000
|
||||
#define E1000_PCS_LCTL_AN_RESTART 0x20000
|
||||
#define E1000_PCS_LCTL_AN_TIMEOUT 0x40000
|
||||
|
||||
#define E1000_PCS_LSTS_LINK_OK 1
|
||||
#define E1000_PCS_LSTS_SPEED_100 2
|
||||
#define E1000_PCS_LSTS_SPEED_1000 4
|
||||
#define E1000_PCS_LSTS_DUPLEX_FULL 8
|
||||
#define E1000_PCS_LSTS_SYNK_OK 0x10
|
||||
|
||||
/* Device Status */
|
||||
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
|
||||
#define E1000_STATUS_FUNC_SHIFT 2
|
||||
#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
|
||||
#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
/* Change in Dock/Undock state. Clear on write '0'. */
|
||||
/* Status of Master requests. */
|
||||
#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000
|
||||
/* BMC external code execution disabled */
|
||||
|
||||
/* Constants used to intrepret the masked PCI-X bus speed. */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
|
||||
#define ADVERTISE_10_HALF 0x0001
|
||||
#define ADVERTISE_10_FULL 0x0002
|
||||
#define ADVERTISE_100_HALF 0x0004
|
||||
#define ADVERTISE_100_FULL 0x0008
|
||||
#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
|
||||
#define ADVERTISE_1000_FULL 0x0020
|
||||
|
||||
/* 1000/H is not supported, nor spec-compliant. */
|
||||
#define E1000_ALL_SPEED_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
|
||||
ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
|
||||
ADVERTISE_1000_FULL)
|
||||
#define E1000_ALL_NOT_GIG (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
|
||||
ADVERTISE_100_HALF | ADVERTISE_100_FULL)
|
||||
#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL)
|
||||
#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL)
|
||||
#define E1000_ALL_FULL_DUPLEX (ADVERTISE_10_FULL | ADVERTISE_100_FULL | \
|
||||
ADVERTISE_1000_FULL)
|
||||
#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF)
|
||||
|
||||
#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX
|
||||
|
||||
/* LED Control */
|
||||
#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
|
||||
#define E1000_LEDCTL_LED0_MODE_SHIFT 0
|
||||
#define E1000_LEDCTL_LED0_IVRT 0x00000040
|
||||
#define E1000_LEDCTL_LED0_BLINK 0x00000080
|
||||
|
||||
#define E1000_LEDCTL_MODE_LED_ON 0xE
|
||||
#define E1000_LEDCTL_MODE_LED_OFF 0xF
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
|
||||
/* Extended desc bits for Linksec and timesync */
|
||||
|
||||
/* Transmit Control */
|
||||
#define E1000_TCTL_EN 0x00000002 /* enable tx */
|
||||
#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
|
||||
#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
|
||||
#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
|
||||
#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
|
||||
|
||||
/* Transmit Arbitration Count */
|
||||
|
||||
/* SerDes Control */
|
||||
#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
|
||||
|
||||
/* Receive Checksum Control */
|
||||
#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
|
||||
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
|
||||
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
|
||||
|
||||
/* Header split receive */
|
||||
|
||||
/* Collision related configuration parameters */
|
||||
#define E1000_COLLISION_THRESHOLD 15
|
||||
#define E1000_CT_SHIFT 4
|
||||
#define E1000_COLLISION_DISTANCE 63
|
||||
#define E1000_COLD_SHIFT 12
|
||||
|
||||
/* Ethertype field values */
|
||||
#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
|
||||
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x3F00
|
||||
|
||||
/* Extended Configuration Control and Size */
|
||||
#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040
|
||||
|
||||
/* PBA constants */
|
||||
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
|
||||
#define E1000_PBA_24K 0x0018
|
||||
#define E1000_PBA_34K 0x0022
|
||||
|
||||
#define IFS_MAX 80
|
||||
#define IFS_MIN 40
|
||||
#define IFS_RATIO 4
|
||||
#define IFS_STEP 10
|
||||
#define MIN_NUM_XMITS 1000
|
||||
|
||||
/* SW Semaphore Register */
|
||||
#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
|
||||
#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
|
||||
|
||||
/* Interrupt Cause Read */
|
||||
#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
|
||||
#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
|
||||
#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
|
||||
#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
|
||||
#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
|
||||
#define E1000_ICR_RXO 0x00000040 /* rx overrun */
|
||||
#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
|
||||
#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
|
||||
#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */
|
||||
#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
|
||||
#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
|
||||
#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
|
||||
#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
|
||||
#define E1000_ICR_TXD_LOW 0x00008000
|
||||
#define E1000_ICR_SRPD 0x00010000
|
||||
#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
|
||||
#define E1000_ICR_MNG 0x00040000 /* Manageability event */
|
||||
#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
|
||||
/* If this bit asserted, the driver should claim the interrupt */
|
||||
#define E1000_ICR_INT_ASSERTED 0x80000000
|
||||
/* queue 0 Rx descriptor FIFO parity error */
|
||||
#define E1000_ICR_RXD_FIFO_PAR0 0x00100000
|
||||
/* queue 0 Tx descriptor FIFO parity error */
|
||||
#define E1000_ICR_TXD_FIFO_PAR0 0x00200000
|
||||
/* host arb read buffer parity error */
|
||||
#define E1000_ICR_HOST_ARB_PAR 0x00400000
|
||||
#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */
|
||||
/* queue 1 Rx descriptor FIFO parity error */
|
||||
#define E1000_ICR_RXD_FIFO_PAR1 0x01000000
|
||||
/* queue 1 Tx descriptor FIFO parity error */
|
||||
#define E1000_ICR_TXD_FIFO_PAR1 0x02000000
|
||||
/* FW changed the status of DISSW bit in the FWSM */
|
||||
#define E1000_ICR_DSW 0x00000020
|
||||
/* LAN connected device generates an interrupt */
|
||||
#define E1000_ICR_PHYINT 0x00001000
|
||||
#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */
|
||||
|
||||
/* Extended Interrupt Cause Read */
|
||||
#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */
|
||||
#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */
|
||||
#define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */
|
||||
#define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */
|
||||
#define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */
|
||||
#define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */
|
||||
#define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */
|
||||
#define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */
|
||||
#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */
|
||||
#define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */
|
||||
/* TCP Timer */
|
||||
|
||||
/*
|
||||
* This defines the bits that are set in the Interrupt Mask
|
||||
* Set/Read Register. Each bit is documented below:
|
||||
* o RXT0 = Receiver Timer Interrupt (ring 0)
|
||||
* o TXDW = Transmit Descriptor Written Back
|
||||
* o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
|
||||
* o RXSEQ = Receive Sequence Error
|
||||
* o LSC = Link Status Change
|
||||
*/
|
||||
#define IMS_ENABLE_MASK ( \
|
||||
E1000_IMS_RXT0 | \
|
||||
E1000_IMS_TXDW | \
|
||||
E1000_IMS_RXDMT0 | \
|
||||
E1000_IMS_RXSEQ | \
|
||||
E1000_IMS_LSC)
|
||||
|
||||
/* Interrupt Mask Set */
|
||||
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
|
||||
#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
|
||||
#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
|
||||
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
|
||||
/* queue 0 Rx descriptor FIFO parity error */
|
||||
/* queue 0 Tx descriptor FIFO parity error */
|
||||
/* host arb read buffer parity error */
|
||||
/* packet buffer parity error */
|
||||
/* queue 1 Rx descriptor FIFO parity error */
|
||||
/* queue 1 Tx descriptor FIFO parity error */
|
||||
|
||||
/* Extended Interrupt Mask Set */
|
||||
#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */
|
||||
#define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */
|
||||
|
||||
/* Interrupt Cause Set */
|
||||
#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
|
||||
#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
/* queue 0 Rx descriptor FIFO parity error */
|
||||
/* queue 0 Tx descriptor FIFO parity error */
|
||||
/* host arb read buffer parity error */
|
||||
/* packet buffer parity error */
|
||||
/* queue 1 Rx descriptor FIFO parity error */
|
||||
/* queue 1 Tx descriptor FIFO parity error */
|
||||
|
||||
/* Extended Interrupt Cause Set */
|
||||
|
||||
/* Transmit Descriptor Control */
|
||||
/* Enable the counting of descriptors still to be processed. */
|
||||
|
||||
/* Flow Control Constants */
|
||||
#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
|
||||
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
|
||||
#define FLOW_CONTROL_TYPE 0x8808
|
||||
|
||||
/* 802.1q VLAN Packet Size */
|
||||
#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
|
||||
#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
|
||||
|
||||
/* Receive Address */
|
||||
/*
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* Technically, we have 16 spots. However, we reserve one of these spots
|
||||
* (RAR[15]) for our directed address used by controllers with
|
||||
* manageability enabled, allowing us room for 15 multicast addresses.
|
||||
*/
|
||||
#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
|
||||
|
||||
/* Error Codes */
|
||||
#define E1000_ERR_NVM 1
|
||||
#define E1000_ERR_PHY 2
|
||||
#define E1000_ERR_CONFIG 3
|
||||
#define E1000_ERR_PARAM 4
|
||||
#define E1000_ERR_MAC_INIT 5
|
||||
#define E1000_ERR_RESET 9
|
||||
#define E1000_ERR_MASTER_REQUESTS_PENDING 10
|
||||
#define E1000_ERR_HOST_INTERFACE_COMMAND 11
|
||||
#define E1000_BLK_PHY_RESET 12
|
||||
#define E1000_ERR_SWFW_SYNC 13
|
||||
#define E1000_NOT_IMPLEMENTED 14
|
||||
|
||||
/* Loop limit on how long we wait for auto-negotiation to complete */
|
||||
#define COPPER_LINK_UP_LIMIT 10
|
||||
#define PHY_AUTO_NEG_LIMIT 45
|
||||
#define PHY_FORCE_LIMIT 20
|
||||
/* Number of 100 microseconds we wait for PCI Express master disable */
|
||||
#define MASTER_DISABLE_TIMEOUT 800
|
||||
/* Number of milliseconds we wait for PHY configuration done after MAC reset */
|
||||
#define PHY_CFG_TIMEOUT 100
|
||||
/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */
|
||||
/* Number of milliseconds for NVM auto read done after MAC reset. */
|
||||
#define AUTO_READ_DONE_TIMEOUT 10
|
||||
|
||||
/* Flow Control */
|
||||
#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
|
||||
|
||||
/* Transmit Configuration Word */
|
||||
#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */
|
||||
|
||||
/* Receive Configuration Word */
|
||||
|
||||
/* PCI Express Control */
|
||||
#define E1000_GCR_RXD_NO_SNOOP 0x00000001
|
||||
#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
|
||||
#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
|
||||
#define E1000_GCR_TXD_NO_SNOOP 0x00000008
|
||||
#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
|
||||
#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
|
||||
|
||||
#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
|
||||
E1000_GCR_RXDSCW_NO_SNOOP | \
|
||||
E1000_GCR_RXDSCR_NO_SNOOP | \
|
||||
E1000_GCR_TXD_NO_SNOOP | \
|
||||
E1000_GCR_TXDSCW_NO_SNOOP | \
|
||||
E1000_GCR_TXDSCR_NO_SNOOP)
|
||||
|
||||
/* PHY Control Register */
|
||||
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
|
||||
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
|
||||
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
|
||||
#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
|
||||
#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
|
||||
#define MII_CR_SPEED_1000 0x0040
|
||||
#define MII_CR_SPEED_100 0x2000
|
||||
#define MII_CR_SPEED_10 0x0000
|
||||
|
||||
/* PHY Status Register */
|
||||
#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
||||
#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
||||
|
||||
/* Autoneg Advertisement Register */
|
||||
#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
|
||||
#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
|
||||
#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
|
||||
#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
|
||||
#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
|
||||
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
|
||||
|
||||
/* Link Partner Ability Register (Base Page) */
|
||||
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
|
||||
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
|
||||
|
||||
/* Autoneg Expansion Register */
|
||||
|
||||
/* 1000BASE-T Control Register */
|
||||
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
|
||||
#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
|
||||
/* 0=DTE device */
|
||||
#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
|
||||
/* 0=Configure PHY as Slave */
|
||||
#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
|
||||
/* 0=Automatic Master/Slave config */
|
||||
|
||||
/* 1000BASE-T Status Register */
|
||||
#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
|
||||
#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
|
||||
|
||||
|
||||
/* PHY 1000 MII Register/Bit Definitions */
|
||||
/* PHY Registers defined by IEEE */
|
||||
#define PHY_CONTROL 0x00 /* Control Register */
|
||||
#define PHY_STATUS 0x01 /* Status Regiser */
|
||||
#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
|
||||
#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
|
||||
#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
|
||||
#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
|
||||
#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
|
||||
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
|
||||
|
||||
/* NVM Control */
|
||||
#define E1000_EECD_SK 0x00000001 /* NVM Clock */
|
||||
#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */
|
||||
#define E1000_EECD_DI 0x00000004 /* NVM Data In */
|
||||
#define E1000_EECD_DO 0x00000008 /* NVM Data Out */
|
||||
#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */
|
||||
#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
|
||||
#define E1000_EECD_PRES 0x00000100 /* NVM Present */
|
||||
/* NVM Addressing bits based on type 0=small, 1=large */
|
||||
#define E1000_EECD_ADDR_BITS 0x00000400
|
||||
#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
|
||||
#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
|
||||
#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
|
||||
#define E1000_EECD_SIZE_EX_SHIFT 11
|
||||
|
||||
/* Offset to data in NVM read/write registers */
|
||||
#define E1000_NVM_RW_REG_DATA 16
|
||||
#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
|
||||
#define E1000_NVM_RW_REG_START 1 /* Start operation */
|
||||
#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
|
||||
#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */
|
||||
|
||||
/* NVM Word Offsets */
|
||||
#define NVM_ID_LED_SETTINGS 0x0004
|
||||
/* For SERDES output amplitude adjustment. */
|
||||
#define NVM_INIT_CONTROL2_REG 0x000F
|
||||
#define NVM_INIT_CONTROL3_PORT_A 0x0024
|
||||
#define NVM_ALT_MAC_ADDR_PTR 0x0037
|
||||
#define NVM_CHECKSUM_REG 0x003F
|
||||
|
||||
#define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */
|
||||
#define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */
|
||||
|
||||
/* Mask bits for fields in Word 0x0f of the NVM */
|
||||
#define NVM_WORD0F_PAUSE_MASK 0x3000
|
||||
#define NVM_WORD0F_ASM_DIR 0x2000
|
||||
|
||||
/* Mask bits for fields in Word 0x1a of the NVM */
|
||||
|
||||
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
|
||||
#define NVM_SUM 0xBABA
|
||||
|
||||
#define NVM_PBA_OFFSET_0 8
|
||||
#define NVM_PBA_OFFSET_1 9
|
||||
#define NVM_WORD_SIZE_BASE_SHIFT 6
|
||||
|
||||
/* NVM Commands - Microwire */
|
||||
|
||||
/* NVM Commands - SPI */
|
||||
#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
|
||||
#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */
|
||||
#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
|
||||
#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */
|
||||
#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */
|
||||
|
||||
/* SPI NVM Status Register */
|
||||
#define NVM_STATUS_RDY_SPI 0x01
|
||||
|
||||
/* 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
|
||||
|
||||
#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF
|
||||
#define IGP_ACTIVITY_LED_ENABLE 0x0300
|
||||
#define IGP_LED3_MODE 0x07000000
|
||||
|
||||
/* PCI/PCI-X/PCI-EX Config space */
|
||||
#define PCI_HEADER_TYPE_REGISTER 0x0E
|
||||
#define PCIE_LINK_STATUS 0x12
|
||||
|
||||
#define PCI_HEADER_TYPE_MULTIFUNC 0x80
|
||||
#define PCIE_LINK_WIDTH_MASK 0x3F0
|
||||
#define PCIE_LINK_WIDTH_SHIFT 4
|
||||
|
||||
#define PHY_REVISION_MASK 0xFFFFFFF0
|
||||
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
|
||||
#define MAX_PHY_MULTI_PAGE_REG 0xF
|
||||
|
||||
/* Bit definitions for valid PHY IDs. */
|
||||
/*
|
||||
* I = Integrated
|
||||
* E = External
|
||||
*/
|
||||
#define M88E1111_I_PHY_ID 0x01410CC0
|
||||
#define IGP03E1000_E_PHY_ID 0x02A80390
|
||||
#define M88_VENDOR 0x0141
|
||||
|
||||
/* M88E1000 Specific Registers */
|
||||
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
|
||||
#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
|
||||
#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
|
||||
|
||||
#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */
|
||||
#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */
|
||||
|
||||
/* M88E1000 PHY Specific Control Register */
|
||||
#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
|
||||
/* 1=CLK125 low, 0=CLK125 toggling */
|
||||
#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
|
||||
/* Manual MDI configuration */
|
||||
#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
|
||||
/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
|
||||
#define M88E1000_PSCR_AUTO_X_1000T 0x0040
|
||||
/* Auto crossover enabled all speeds */
|
||||
#define M88E1000_PSCR_AUTO_X_MODE 0x0060
|
||||
/*
|
||||
* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold
|
||||
* 0=Normal 10BASE-T RX Threshold
|
||||
*/
|
||||
/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
|
||||
#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
|
||||
|
||||
/* M88E1000 PHY Specific Status Register */
|
||||
#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
|
||||
#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
|
||||
#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
|
||||
/*
|
||||
* 0 = <50M
|
||||
* 1 = 50-80M
|
||||
* 2 = 80-110M
|
||||
* 3 = 110-140M
|
||||
* 4 = >140M
|
||||
*/
|
||||
#define M88E1000_PSSR_CABLE_LENGTH 0x0380
|
||||
#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
|
||||
#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
|
||||
|
||||
#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
|
||||
|
||||
/* M88E1000 Extended PHY Specific Control Register */
|
||||
/*
|
||||
* 1 = Lost lock detect enabled.
|
||||
* Will assert lost lock and bring
|
||||
* link down if idle not seen
|
||||
* within 1ms in 1000BASE-T
|
||||
*/
|
||||
/*
|
||||
* Number of times we will attempt to autonegotiate before downshifting if we
|
||||
* are the master
|
||||
*/
|
||||
#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
|
||||
#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000
|
||||
/*
|
||||
* Number of times we will attempt to autonegotiate before downshifting if we
|
||||
* are the slave
|
||||
*/
|
||||
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300
|
||||
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
|
||||
#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
|
||||
|
||||
/* M88EC018 Rev 2 specific DownShift settings */
|
||||
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
|
||||
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
|
||||
|
||||
/* MDI Control */
|
||||
#define E1000_MDIC_REG_SHIFT 16
|
||||
#define E1000_MDIC_PHY_SHIFT 21
|
||||
#define E1000_MDIC_OP_WRITE 0x04000000
|
||||
#define E1000_MDIC_OP_READ 0x08000000
|
||||
#define E1000_MDIC_READY 0x10000000
|
||||
#define E1000_MDIC_ERROR 0x40000000
|
||||
|
||||
/* SerDes Control */
|
||||
#define E1000_GEN_CTL_READY 0x80000000
|
||||
#define E1000_GEN_CTL_ADDRESS_SHIFT 8
|
||||
#define E1000_GEN_POLL_TIMEOUT 640
|
||||
|
||||
#endif
|
599
drivers/net/igb/e1000_hw.h
Normal file
599
drivers/net/igb/e1000_hw.h
Normal file
|
@ -0,0 +1,599 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) Gigabit Ethernet Linux driver
|
||||
Copyright(c) 2007 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_HW_H_
|
||||
#define _E1000_HW_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_regs.h"
|
||||
#include "e1000_defines.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
|
||||
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
|
||||
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
|
||||
|
||||
#define E1000_REVISION_2 2
|
||||
#define E1000_REVISION_4 4
|
||||
|
||||
#define E1000_FUNC_1 1
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_82575,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
enum e1000_media_type {
|
||||
e1000_media_type_unknown = 0,
|
||||
e1000_media_type_copper = 1,
|
||||
e1000_media_type_fiber = 2,
|
||||
e1000_media_type_internal_serdes = 3,
|
||||
e1000_num_media_types
|
||||
};
|
||||
|
||||
enum e1000_nvm_type {
|
||||
e1000_nvm_unknown = 0,
|
||||
e1000_nvm_none,
|
||||
e1000_nvm_eeprom_spi,
|
||||
e1000_nvm_eeprom_microwire,
|
||||
e1000_nvm_flash_hw,
|
||||
e1000_nvm_flash_sw
|
||||
};
|
||||
|
||||
enum e1000_nvm_override {
|
||||
e1000_nvm_override_none = 0,
|
||||
e1000_nvm_override_spi_small,
|
||||
e1000_nvm_override_spi_large,
|
||||
e1000_nvm_override_microwire_small,
|
||||
e1000_nvm_override_microwire_large
|
||||
};
|
||||
|
||||
enum e1000_phy_type {
|
||||
e1000_phy_unknown = 0,
|
||||
e1000_phy_none,
|
||||
e1000_phy_m88,
|
||||
e1000_phy_igp,
|
||||
e1000_phy_igp_2,
|
||||
e1000_phy_gg82563,
|
||||
e1000_phy_igp_3,
|
||||
e1000_phy_ife,
|
||||
};
|
||||
|
||||
enum e1000_bus_type {
|
||||
e1000_bus_type_unknown = 0,
|
||||
e1000_bus_type_pci,
|
||||
e1000_bus_type_pcix,
|
||||
e1000_bus_type_pci_express,
|
||||
e1000_bus_type_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_speed {
|
||||
e1000_bus_speed_unknown = 0,
|
||||
e1000_bus_speed_33,
|
||||
e1000_bus_speed_66,
|
||||
e1000_bus_speed_100,
|
||||
e1000_bus_speed_120,
|
||||
e1000_bus_speed_133,
|
||||
e1000_bus_speed_2500,
|
||||
e1000_bus_speed_5000,
|
||||
e1000_bus_speed_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_width {
|
||||
e1000_bus_width_unknown = 0,
|
||||
e1000_bus_width_pcie_x1,
|
||||
e1000_bus_width_pcie_x2,
|
||||
e1000_bus_width_pcie_x4 = 4,
|
||||
e1000_bus_width_pcie_x8 = 8,
|
||||
e1000_bus_width_32,
|
||||
e1000_bus_width_64,
|
||||
e1000_bus_width_reserved
|
||||
};
|
||||
|
||||
enum e1000_1000t_rx_status {
|
||||
e1000_1000t_rx_status_not_ok = 0,
|
||||
e1000_1000t_rx_status_ok,
|
||||
e1000_1000t_rx_status_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_rev_polarity {
|
||||
e1000_rev_polarity_normal = 0,
|
||||
e1000_rev_polarity_reversed,
|
||||
e1000_rev_polarity_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_fc_type {
|
||||
e1000_fc_none = 0,
|
||||
e1000_fc_rx_pause,
|
||||
e1000_fc_tx_pause,
|
||||
e1000_fc_full,
|
||||
e1000_fc_default = 0xFF
|
||||
};
|
||||
|
||||
|
||||
/* Receive Descriptor */
|
||||
struct e1000_rx_desc {
|
||||
u64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
u16 length; /* Length of data DMAed into data buffer */
|
||||
u16 csum; /* Packet checksum */
|
||||
u8 status; /* Descriptor status */
|
||||
u8 errors; /* Descriptor Errors */
|
||||
u16 special;
|
||||
};
|
||||
|
||||
/* Receive Descriptor - Extended */
|
||||
union e1000_rx_desc_extended {
|
||||
struct {
|
||||
u64 buffer_addr;
|
||||
u64 reserved;
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
u32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length;
|
||||
u16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define MAX_PS_BUFFERS 4
|
||||
/* Receive Descriptor - Packet Split */
|
||||
union e1000_rx_desc_packet_split {
|
||||
struct {
|
||||
/* one buffer for protocol header(s), three data buffers */
|
||||
u64 buffer_addr[MAX_PS_BUFFERS];
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
u32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length0; /* length of buffer 0 */
|
||||
u16 vlan; /* VLAN tag */
|
||||
} middle;
|
||||
struct {
|
||||
u16 header_status;
|
||||
u16 length[3]; /* length of buffers 1-3 */
|
||||
} upper;
|
||||
u64 reserved;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Transmit Descriptor */
|
||||
struct e1000_tx_desc {
|
||||
u64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u16 length; /* Data buffer length */
|
||||
u8 cso; /* Checksum offset */
|
||||
u8 cmd; /* Descriptor control */
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 css; /* Checksum start */
|
||||
u16 special;
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
||||
/* Offload Context Descriptor */
|
||||
struct e1000_context_desc {
|
||||
union {
|
||||
u32 ip_config;
|
||||
struct {
|
||||
u8 ipcss; /* IP checksum start */
|
||||
u8 ipcso; /* IP checksum offset */
|
||||
u16 ipcse; /* IP checksum end */
|
||||
} ip_fields;
|
||||
} lower_setup;
|
||||
union {
|
||||
u32 tcp_config;
|
||||
struct {
|
||||
u8 tucss; /* TCP checksum start */
|
||||
u8 tucso; /* TCP checksum offset */
|
||||
u16 tucse; /* TCP checksum end */
|
||||
} tcp_fields;
|
||||
} upper_setup;
|
||||
u32 cmd_and_length;
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 hdr_len; /* Header length */
|
||||
u16 mss; /* Maximum segment size */
|
||||
} fields;
|
||||
} tcp_seg_setup;
|
||||
};
|
||||
|
||||
/* Offload data descriptor */
|
||||
struct e1000_data_desc {
|
||||
u64 buffer_addr; /* Address of the descriptor's buffer address */
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u16 length; /* Data buffer length */
|
||||
u8 typ_len_ext;
|
||||
u8 cmd;
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 popts; /* Packet Options */
|
||||
u16 special;
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct e1000_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 cexterr;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 tsctfc;
|
||||
u64 iac;
|
||||
u64 icrxptc;
|
||||
u64 icrxatc;
|
||||
u64 ictxptc;
|
||||
u64 ictxatc;
|
||||
u64 ictxqec;
|
||||
u64 ictxqmtc;
|
||||
u64 icrxdmtc;
|
||||
u64 icrxoc;
|
||||
u64 cbtmpc;
|
||||
u64 htdpmc;
|
||||
u64 cbrdpc;
|
||||
u64 cbrmpc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 htcbdpc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
};
|
||||
|
||||
struct e1000_phy_stats {
|
||||
u32 idle_errors;
|
||||
u32 receive_errors;
|
||||
};
|
||||
|
||||
struct e1000_host_mng_dhcp_cookie {
|
||||
u32 signature;
|
||||
u8 status;
|
||||
u8 reserved0;
|
||||
u16 vlan_id;
|
||||
u32 reserved1;
|
||||
u16 reserved2;
|
||||
u8 reserved3;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 1" */
|
||||
struct e1000_host_command_header {
|
||||
u8 command_id;
|
||||
u8 command_length;
|
||||
u8 command_options;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_DATA_LENGTH 252
|
||||
struct e1000_host_command_info {
|
||||
struct e1000_host_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 2" */
|
||||
struct e1000_host_mng_command_header {
|
||||
u8 command_id;
|
||||
u8 checksum;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u16 command_length;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
|
||||
struct e1000_host_mng_command_info {
|
||||
struct e1000_host_mng_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
|
||||
};
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_phy.h"
|
||||
#include "e1000_nvm.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
s32 (*setup_physical_interface)(struct e1000_hw *);
|
||||
void (*rar_set)(struct e1000_hw *, u8 *, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
|
||||
};
|
||||
|
||||
struct e1000_phy_operations {
|
||||
s32 (*acquire_phy)(struct e1000_hw *);
|
||||
s32 (*force_speed_duplex)(struct e1000_hw *);
|
||||
s32 (*get_cfg_done)(struct e1000_hw *hw);
|
||||
s32 (*get_cable_length)(struct e1000_hw *);
|
||||
s32 (*get_phy_info)(struct e1000_hw *);
|
||||
s32 (*read_phy_reg)(struct e1000_hw *, u32, u16 *);
|
||||
void (*release_phy)(struct e1000_hw *);
|
||||
s32 (*reset_phy)(struct e1000_hw *);
|
||||
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*write_phy_reg)(struct e1000_hw *, u32, u16);
|
||||
};
|
||||
|
||||
struct e1000_nvm_operations {
|
||||
s32 (*acquire_nvm)(struct e1000_hw *);
|
||||
s32 (*read_nvm)(struct e1000_hw *, u16, u16, u16 *);
|
||||
void (*release_nvm)(struct e1000_hw *);
|
||||
s32 (*write_nvm)(struct e1000_hw *, u16, u16, u16 *);
|
||||
};
|
||||
|
||||
struct e1000_info {
|
||||
s32 (*get_invariants)(struct e1000_hw *);
|
||||
struct e1000_mac_operations *mac_ops;
|
||||
struct e1000_phy_operations *phy_ops;
|
||||
struct e1000_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct e1000_info e1000_82575_info;
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u32 collision_delta;
|
||||
u32 ledctl_default;
|
||||
u32 ledctl_mode1;
|
||||
u32 ledctl_mode2;
|
||||
u32 mc_filter_type;
|
||||
u32 tx_packet_delta;
|
||||
u32 txcw;
|
||||
|
||||
u16 current_ifs_val;
|
||||
u16 ifs_max_val;
|
||||
u16 ifs_min_val;
|
||||
u16 ifs_ratio;
|
||||
u16 ifs_step_size;
|
||||
u16 mta_reg_count;
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool adaptive_ifs;
|
||||
bool arc_subsystem_valid;
|
||||
bool asf_firmware_present;
|
||||
bool autoneg;
|
||||
bool autoneg_failed;
|
||||
bool disable_av;
|
||||
bool disable_hw_init_bits;
|
||||
bool get_link_status;
|
||||
bool ifs_params_forced;
|
||||
bool in_ifs_mode;
|
||||
bool report_tx_early;
|
||||
bool serdes_has_link;
|
||||
bool tx_pkt_filtering;
|
||||
};
|
||||
|
||||
struct e1000_phy_info {
|
||||
struct e1000_phy_operations ops;
|
||||
|
||||
enum e1000_phy_type type;
|
||||
|
||||
enum e1000_1000t_rx_status local_rx;
|
||||
enum e1000_1000t_rx_status remote_rx;
|
||||
enum e1000_ms_type ms_type;
|
||||
enum e1000_ms_type original_ms_type;
|
||||
enum e1000_rev_polarity cable_polarity;
|
||||
enum e1000_smart_speed smart_speed;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum e1000_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
u16 cable_length;
|
||||
u16 max_cable_length;
|
||||
u16 min_cable_length;
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool disable_polarity_correction;
|
||||
bool is_mdix;
|
||||
bool polarity_correction;
|
||||
bool reset_disable;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct e1000_nvm_info {
|
||||
struct e1000_nvm_operations ops;
|
||||
|
||||
enum e1000_nvm_type type;
|
||||
enum e1000_nvm_override override;
|
||||
|
||||
u32 flash_bank_size;
|
||||
u32 flash_base_addr;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct e1000_bus_info {
|
||||
enum e1000_bus_type type;
|
||||
enum e1000_bus_speed speed;
|
||||
enum e1000_bus_width width;
|
||||
|
||||
u32 snoop;
|
||||
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
struct e1000_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum e1000_fc_type type; /* Type of flow control */
|
||||
enum e1000_fc_type original_type;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
void *dev_spec;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_fc_info fc;
|
||||
struct e1000_phy_info phy;
|
||||
struct e1000_nvm_info nvm;
|
||||
struct e1000_bus_info bus;
|
||||
struct e1000_host_mng_dhcp_cookie mng_cookie;
|
||||
|
||||
u32 dev_spec_size;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char *igb_get_hw_dev_name(struct e1000_hw *hw);
|
||||
#define hw_dbg(hw, format, arg...) \
|
||||
printk(KERN_DEBUG "%s: " format, igb_get_hw_dev_name(hw), ##arg)
|
||||
#else
|
||||
static inline int __attribute__ ((format (printf, 2, 3)))
|
||||
hw_dbg(struct e1000_hw *hw, const char *format, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue