mirror of https://gitee.com/openkylin/linux.git
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
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:
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
|
|||
/* 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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for the Linux Controller Area Network drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_CAN_VCAN) += vcan.o
|
|
@ -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 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
|
|||
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 @@ static void lance_tx(struct net_device *dev)
|
|||
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 @@ e1000_set_ringparam(struct net_device *netdev,
|
|||
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 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
|
||||
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 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
|
|||
|
||||
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 @@ static int e1000_set_ringparam(struct net_device *netdev,
|
|||
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 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
|
||||
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 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
|
|||
|
||||
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);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 @@ special acknowledgements to:
|
|||
#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);
|
||||
|
|
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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 New Issue