summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/libucl/tests/.gitignore8
-rw-r--r--contrib/unbound/.gitignore38
-rw-r--r--etc/Makefile3
-rw-r--r--etc/defaults/periodic.conf5
-rw-r--r--etc/defaults/rc.conf11
-rw-r--r--etc/mtree/BSD.var.dist2
-rw-r--r--etc/ntp.conf7
-rw-r--r--etc/ntp/Makefile10
-rw-r--r--etc/ntp/leap-seconds221
-rwxr-xr-xetc/periodic/daily/480.leapfile-ntpd28
-rw-r--r--etc/periodic/daily/Makefile3
-rwxr-xr-xetc/rc.d/ntpd67
-rw-r--r--lib/libdevctl/devctl.37
-rw-r--r--lib/libprocstat/libprocstat.c8
-rw-r--r--lib/libutil/kinfo_getfile.c4
-rw-r--r--lib/libutil/kinfo_getvmmap.c4
-rw-r--r--share/man/man5/core.525
-rw-r--r--sys/boot/arm/at91/boot2/boot2.c44
-rw-r--r--sys/boot/arm/ixp425/boot2/boot2.c42
-rw-r--r--sys/boot/common/load_elf.c2
-rw-r--r--sys/boot/common/paths.h39
-rw-r--r--sys/boot/common/rbx.h (renamed from sys/boot/i386/common/rbx.h)0
-rw-r--r--sys/boot/efi/Makefile4
-rw-r--r--sys/boot/efi/boot1/boot1.c575
-rw-r--r--sys/boot/efi/boot1/boot_module.h13
-rw-r--r--sys/boot/efi/boot1/ufs_module.c53
-rw-r--r--sys/boot/efi/boot1/zfs_module.c59
-rw-r--r--sys/boot/efi/include/efidevp.h13
-rw-r--r--sys/boot/efi/libefi/Makefile6
-rw-r--r--sys/boot/efi/libefi/libefi.c4
-rw-r--r--sys/boot/efi/loader/main.c230
-rw-r--r--sys/boot/i386/boot2/boot2.c49
-rw-r--r--sys/boot/i386/gptboot/gptboot.c10
-rw-r--r--sys/boot/i386/loader/main.c29
-rw-r--r--sys/boot/i386/zfsboot/zfsboot.c10
-rw-r--r--sys/boot/ia64/efi/main.c3
-rw-r--r--sys/boot/pc98/boot2/boot2.c49
-rw-r--r--sys/boot/powerpc/boot1.chrp/boot1.c5
-rw-r--r--sys/boot/sparc64/boot1/boot1.c6
-rw-r--r--sys/boot/userboot/userboot/main.c27
-rw-r--r--sys/boot/zfs/libzfs.h1
-rw-r--r--sys/boot/zfs/zfs.c31
-rw-r--r--sys/conf/files2
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/dev/ixgbe/if_ix.c728
-rw-r--r--sys/dev/ixgbe/if_ixv.c134
-rw-r--r--sys/dev/ixgbe/ix_txrx.c123
-rw-r--r--sys/dev/ixgbe/ixgbe.h37
-rw-r--r--sys/dev/ixgbe/ixgbe_82598.c4
-rw-r--r--sys/dev/ixgbe/ixgbe_82599.c61
-rw-r--r--sys/dev/ixgbe/ixgbe_api.c6
-rw-r--r--sys/dev/ixgbe/ixgbe_api.h9
-rw-r--r--sys/dev/ixgbe/ixgbe_common.c69
-rw-r--r--sys/dev/ixgbe/ixgbe_dcb.c7
-rw-r--r--sys/dev/ixgbe/ixgbe_osdep.c (renamed from sys/dev/ixgbe/LICENSE)55
-rw-r--r--sys/dev/ixgbe/ixgbe_osdep.h67
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.c85
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.h13
-rw-r--r--sys/dev/ixgbe/ixgbe_type.h64
-rw-r--r--sys/dev/ixgbe/ixgbe_vf.c2
-rw-r--r--sys/dev/ixgbe/ixgbe_x540.c44
-rw-r--r--sys/dev/ixgbe/ixgbe_x550.c392
-rw-r--r--sys/dev/ixgbe/ixgbe_x550.h3
-rw-r--r--sys/dev/random/live_entropy_sources.c4
-rw-r--r--sys/dev/random/live_entropy_sources.h2
-rw-r--r--sys/dev/random/random_adaptors.c4
-rw-r--r--sys/dev/random/random_adaptors.h4
-rw-r--r--sys/dev/random/random_harvestq.c30
-rw-r--r--sys/dev/random/randomdev.c23
-rw-r--r--sys/dev/random/randomdev_soft.c6
-rw-r--r--sys/dev/sfxge/common/efx.h8
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.c212
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.h8
-rw-r--r--sys/dev/sfxge/common/efx_phy.c32
-rw-r--r--sys/dev/sfxge/sfxge.c24
-rw-r--r--sys/kern/imgact_elf.c77
-rw-r--r--sys/kern/kern_descrip.c40
-rw-r--r--sys/kern/kern_exec.c10
-rw-r--r--sys/kern/kern_proc.c23
-rw-r--r--sys/modules/ix/Makefile2
-rw-r--r--sys/modules/ixv/Makefile2
-rw-r--r--sys/sys/exec.h3
-rw-r--r--sys/sys/user.h11
-rw-r--r--usr.sbin/devctl/devctl.84
84 files changed, 2931 insertions, 1260 deletions
diff --git a/contrib/libucl/tests/.gitignore b/contrib/libucl/tests/.gitignore
deleted file mode 100644
index 5a48681..0000000
--- a/contrib/libucl/tests/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-*.log
-*.trs
-*.plist
-
-test_basic
-test_generate
-test_schema
-test_speed
diff --git a/contrib/unbound/.gitignore b/contrib/unbound/.gitignore
deleted file mode 100644
index 7fed8d7..0000000
--- a/contrib/unbound/.gitignore
+++ /dev/null
@@ -1,38 +0,0 @@
-*.lo
-*.o
-/.libs/
-/Makefile
-/autom4te.cache/
-/config.h
-/config.log
-/config.status
-/dnstap/dnstap_config.h
-/doc/example.conf
-/doc/libunbound.3
-/doc/unbound-anchor.8
-/doc/unbound-checkconf.8
-/doc/unbound-control.8
-/doc/unbound-host.1
-/doc/unbound.8
-/doc/unbound.conf.5
-/libtool
-/libunbound.la
-/smallapp/unbound-control-setup.sh
-/unbound
-/unbound-anchor
-/unbound-checkconf
-/unbound-control
-/unbound-control-setup
-/unbound-host
-/unbound.h
-/asynclook
-/delayer
-/lock-verify
-/memstats
-/perf
-/petal
-/pktview
-/streamtcp
-/testbound
-/unittest
-
diff --git a/etc/Makefile b/etc/Makefile
index 1030f5f..ffc299f 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -244,6 +244,9 @@ distribution:
${_+_}cd ${.CURDIR}/defaults; ${MAKE} install
${_+_}cd ${.CURDIR}/devd; ${MAKE} install
${_+_}cd ${.CURDIR}/gss; ${MAKE} install
+.if ${MK_NTP} != "no"
+ ${_+_}cd ${.CURDIR}/ntp; ${MAKE} install
+.endif
${_+_}cd ${.CURDIR}/periodic; ${MAKE} install
.if ${MK_PKGBOOTSTRAP} != "no"
${_+_}cd ${.CURDIR}/pkg; ${MAKE} install
diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf
index d97bd93..487a356 100644
--- a/etc/defaults/periodic.conf
+++ b/etc/defaults/periodic.conf
@@ -138,6 +138,11 @@ daily_status_mail_rejects_enable="YES" # Check mail rejects
daily_status_mail_rejects_logs=3 # How many logs to check
daily_status_mail_rejects_shorten="NO" # Shorten output
+# 480.leapfile-ntpd
+daily_ntpd_leapfile_enable="NO" # Fetch NTP leapfile
+daily_ntpd_avoid_congestion="YES" # Avoid congesting
+ # leapfile sources
+
# 480.status-ntpd
daily_status_ntpd_enable="NO" # Check NTP status
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index da3158c..ddaf657 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -366,6 +366,17 @@ ntpd_config="/etc/ntp.conf" # ntpd(8) configuration file
ntpd_sync_on_start="NO" # Sync time on ntpd startup, even if offset is high
ntpd_flags="-p /var/run/ntpd.pid -f /var/db/ntpd.drift"
# Flags to ntpd (if enabled).
+ntp_src_leapfile="/etc/ntp/leap-seconds"
+ # Initial source for ntpd leapfile
+ntp_db_leapfile="/var/db/ntpd.leap-seconds.list"
+ # Working copy (updated weekly) leapfile
+ntp_leapfile_sources="https://www.ietf.org/timezones/data/leap-seconds.list"
+ # Source from which to fetch leapfile
+ntp_leapfile_fetch_opts="-mq" # Options to use for ntp leapfile fetch,
+ # e.g. --no-verify-peer
+ntp_leapfile_expiry_days=30 # Check for new leapfile 30 days prior to
+ # expiry.
+ntp_leapfile_fetch_verbose="NO" # Be verbose during NTP leapfile fetch
# Network Information Services (NIS) options: All need rpcbind_enable="YES" ###
nis_client_enable="NO" # We're an NIS client (or NO).
diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist
index 2403814..4082ad4 100644
--- a/etc/mtree/BSD.var.dist
+++ b/etc/mtree/BSD.var.dist
@@ -46,6 +46,8 @@
..
ipf mode=0700
..
+ ntp mode=0700
+ ..
pkg
..
ports
diff --git a/etc/ntp.conf b/etc/ntp.conf
index ea39877..64edd93 100644
--- a/etc/ntp.conf
+++ b/etc/ntp.conf
@@ -77,3 +77,10 @@ restrict 127.127.1.0
#
#server 127.127.1.0
#fudge 127.127.1.0 stratum 10
+
+# See http://support.ntp.org/bin/view/Support/ConfiguringNTP#Section_6.14.
+# for documentation regarding leapfile. Updates to the file can be obtained
+# from ftp://time.nist.gov/pub/ or ftp://tycho.usno.navy.mil/pub/ntp/.
+# Use either leapfile in /etc/ntp or weekly updated leapfile in /var/db.
+#leapfile "/etc/ntp/leap-seconds"
+leapfile "/var/db/ntpd.leap-seconds.list"
diff --git a/etc/ntp/Makefile b/etc/ntp/Makefile
new file mode 100644
index 0000000..f1aff4f
--- /dev/null
+++ b/etc/ntp/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+NO_OBJ=
+
+FILES= leap-seconds
+
+FILESDIR= /etc/ntp
+FILESMODE= 644
+
+.include <bsd.prog.mk>
diff --git a/etc/ntp/leap-seconds b/etc/ntp/leap-seconds
new file mode 100644
index 0000000..8fa6225
--- /dev/null
+++ b/etc/ntp/leap-seconds
@@ -0,0 +1,221 @@
+#
+# $FreeBSD$
+#
+# In the following text, the symbol '#' introduces
+# a comment, which continues from that symbol until
+# the end of the line. A plain comment line has a
+# whitespace character following the comment indicator.
+# There are also special comment lines defined below.
+# A special comment will always have a non-whitespace
+# character in column 2.
+#
+# A blank line should be ignored.
+#
+# The following table shows the corrections that must
+# be applied to compute International Atomic Time (TAI)
+# from the Coordinated Universal Time (UTC) values that
+# are transmitted by almost all time services.
+#
+# The first column shows an epoch as a number of seconds
+# since 1900.0 and the second column shows the number of
+# seconds that must be added to UTC to compute TAI for
+# any timestamp at or after that epoch. The value on
+# each line is valid from the indicated initial instant
+# until the epoch given on the next one or indefinitely
+# into the future if there is no next line.
+# (The comment on each line shows the representation of
+# the corresponding initial epoch in the usual
+# day-month-year format. The epoch always begins at
+# 00:00:00 UTC on the indicated day. See Note 5 below.)
+#
+# Important notes:
+#
+# 1. Coordinated Universal Time (UTC) is often referred to
+# as Greenwich Mean Time (GMT). The GMT time scale is no
+# longer used, and the use of GMT to designate UTC is
+# discouraged.
+#
+# 2. The UTC time scale is realized by many national
+# laboratories and timing centers. Each laboratory
+# identifies its realization with its name: Thus
+# UTC(NIST), UTC(USNO), etc. The differences among
+# these different realizations are typically on the
+# order of a few nanoseconds (i.e., 0.000 000 00x s)
+# and can be ignored for many purposes. These differences
+# are tabulated in Circular T, which is published monthly
+# by the International Bureau of Weights and Measures
+# (BIPM). See www.bipm.fr for more information.
+#
+# 3. The current defintion of the relationship between UTC
+# and TAI dates from 1 January 1972. A number of different
+# time scales were in use before than epoch, and it can be
+# quite difficult to compute precise timestamps and time
+# intervals in those "prehistoric" days. For more information,
+# consult:
+#
+# The Explanatory Supplement to the Astronomical
+# Ephemeris.
+# or
+# Terry Quinn, "The BIPM and the Accurate Measurement
+# of Time," Proc. of the IEEE, Vol. 79, pp. 894-905,
+# July, 1991.
+#
+# 4. The insertion of leap seconds into UTC is currently the
+# responsibility of the International Earth Rotation Service,
+# which is located at the Paris Observatory:
+#
+# Central Bureau of IERS
+# 61, Avenue de l'Observatoire
+# 75014 Paris, France.
+#
+# Leap seconds are announced by the IERS in its Bulletin C
+#
+# See hpiers.obspm.fr or www.iers.org for more details.
+#
+# All national laboratories and timing centers use the
+# data from the BIPM and the IERS to construct their
+# local realizations of UTC.
+#
+# Although the definition also includes the possibility
+# of dropping seconds ("negative" leap seconds), this has
+# never been done and is unlikely to be necessary in the
+# foreseeable future.
+#
+# 5. If your system keeps time as the number of seconds since
+# some epoch (e.g., NTP timestamps), then the algorithm for
+# assigning a UTC time stamp to an event that happens during a positive
+# leap second is not well defined. The official name of that leap
+# second is 23:59:60, but there is no way of representing that time
+# in these systems.
+# Many systems of this type effectively stop the system clock for
+# one second during the leap second and use a time that is equivalent
+# to 23:59:59 UTC twice. For these systems, the corresponding TAI
+# timestamp would be obtained by advancing to the next entry in the
+# following table when the time equivalent to 23:59:59 UTC
+# is used for the second time. Thus the leap second which
+# occurred on 30 June 1972 at 23:59:59 UTC would have TAI
+# timestamps computed as follows:
+#
+# ...
+# 30 June 1972 23:59:59 (2287785599, first time): TAI= UTC + 10 seconds
+# 30 June 1972 23:59:60 (2287785599,second time): TAI= UTC + 11 seconds
+# 1 July 1972 00:00:00 (2287785600) TAI= UTC + 11 seconds
+# ...
+#
+# If your system realizes the leap second by repeating 00:00:00 UTC twice
+# (this is possible but not usual), then the advance to the next entry
+# in the table must occur the second time that a time equivlent to
+# 00:00:00 UTC is used. Thus, using the same example as above:
+#
+# ...
+# 30 June 1972 23:59:59 (2287785599): TAI= UTC + 10 seconds
+# 30 June 1972 23:59:60 (2287785600, first time): TAI= UTC + 10 seconds
+# 1 July 1972 00:00:00 (2287785600,second time): TAI= UTC + 11 seconds
+# ...
+#
+# in both cases the use of timestamps based on TAI produces a smooth
+# time scale with no discontinuity in the time interval.
+#
+# This complexity would not be needed for negative leap seconds (if they
+# are ever used). The UTC time would skip 23:59:59 and advance from
+# 23:59:58 to 00:00:00 in that case. The TAI offset would decrease by
+# 1 second at the same instant. This is a much easier situation to deal
+# with, since the difficulty of unambiguously representing the epoch
+# during the leap second does not arise.
+#
+# Questions or comments to:
+# Jeff Prillaman
+# Time Service Department
+# US Naval Observatory
+# Washington, DC
+# jeffrey.prillaman@usno.navy.mil
+#
+# Last Update of leap second values: 31 Dec 2015
+#
+# The following line shows this last update date in NTP timestamp
+# format. This is the date on which the most recent change to
+# the leap second data was added to the file. This line can
+# be identified by the unique pair of characters in the first two
+# columns as shown below.
+#
+#$ 3660508800
+#
+# The data in this file will be updated periodically as new leap
+# seconds are announced. In addition to being entered on the line
+# above, the update time (in NTP format) will be added to the basic
+# file name leap-seconds to form the name leap-seconds.<NTP TIME>.
+# In addition, the generic name leap-seconds.list will always point to
+# the most recent version of the file.
+#
+# This update procedure will be performed only when a new leap second
+# is announced.
+#
+# The following entry specifies the expiration date of the data
+# in this file in units of seconds since 1900.0. This expiration date
+# will be changed at least twice per year whether or not a new leap
+# second is announced. These semi-annual changes will be made no
+# later than 1 June and 1 December of each year to indicate what
+# action (if any) is to be taken on 30 June and 31 December,
+# respectively. (These are the customary effective dates for new
+# leap seconds.) This expiration date will be identified by a
+# unique pair of characters in columns 1 and 2 as shown below.
+# In the unlikely event that a leap second is announced with an
+# effective date other than 30 June or 31 December, then this
+# file will be edited to include that leap second as soon as it is
+# announced or at least one month before the effective date
+# (whichever is later).
+# If an announcement by the IERS specifies that no leap second is
+# scheduled, then only the expiration date of the file will
+# be advanced to show that the information in the file is still
+# current -- the update time stamp, the data and the name of the file
+# will not change.
+#
+# Updated through IERS Bulletin C 50
+# File expires on: 1 Jun 2016
+#
+#@ 3673728000
+#
+2272060800 10 # 1 Jan 1972
+2287785600 11 # 1 Jul 1972
+2303683200 12 # 1 Jan 1973
+2335219200 13 # 1 Jan 1974
+2366755200 14 # 1 Jan 1975
+2398291200 15 # 1 Jan 1976
+2429913600 16 # 1 Jan 1977
+2461449600 17 # 1 Jan 1978
+2492985600 18 # 1 Jan 1979
+2524521600 19 # 1 Jan 1980
+2571782400 20 # 1 Jul 1981
+2603318400 21 # 1 Jul 1982
+2634854400 22 # 1 Jul 1983
+2698012800 23 # 1 Jul 1985
+2776982400 24 # 1 Jan 1988
+2840140800 25 # 1 Jan 1990
+2871676800 26 # 1 Jan 1991
+2918937600 27 # 1 Jul 1992
+2950473600 28 # 1 Jul 1993
+2982009600 29 # 1 Jul 1994
+3029443200 30 # 1 Jan 1996
+3076704000 31 # 1 Jul 1997
+3124137600 32 # 1 Jan 1999
+3345062400 33 # 1 Jan 2006
+3439756800 34 # 1 Jan 2009
+3550089600 35 # 1 Jul 2012
+3644697600 36 # 1 Jul 2015
+#
+# the following special comment contains the
+# hash value of the data in this file computed
+# use the secure hash algorithm as specified
+# by FIPS 180-1. See the files in ~/sha for
+# the details of how this hash value is
+# computed. Note that the hash computation
+# ignores comments and whitespace characters
+# in data lines. It includes the NTP values
+# of both the last modification time and the
+# expiration time of the file, but not the
+# white space on those lines.
+# the hash line is also ignored in the
+# computation.
+#
+#h 44a44c49 35b22601 a9c7054c 8c56cf57 9b6f6ed5
+#
diff --git a/etc/periodic/daily/480.leapfile-ntpd b/etc/periodic/daily/480.leapfile-ntpd
new file mode 100755
index 0000000..8429824
--- /dev/null
+++ b/etc/periodic/daily/480.leapfile-ntpd
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# If there is a global system configuration file, suck it in.
+#
+if [ -r /etc/defaults/periodic.conf ]
+then
+ . /etc/defaults/periodic.conf
+ source_periodic_confs
+fi
+
+case "$daily_ntpd_leapfile_enable" in
+ [Yy][Ee][Ss])
+ case "$daily_ntpd_avoid_congestion" in
+ [Yy][Ee][Ss])
+ # Avoid dogpiling
+ (sleep $(jot -r 1 0 86400); service ntpd fetch) &
+ ;;
+ *)
+ service ntpd fetch
+ ;;
+ esac
+ ;;
+esac
+
+exit $rc
diff --git a/etc/periodic/daily/Makefile b/etc/periodic/daily/Makefile
index 593c0f6..617af49 100644
--- a/etc/periodic/daily/Makefile
+++ b/etc/periodic/daily/Makefile
@@ -34,7 +34,8 @@ FILES+= 130.clean-msgs
.endif
.if ${MK_NTP} != "no"
-FILES+= 480.status-ntpd
+FILES+= 480.status-ntpd \
+ 480.leapfile-ntpd
.endif
.if ${MK_PKGTOOLS} != "no"
diff --git a/etc/rc.d/ntpd b/etc/rc.d/ntpd
index 3935b29..7f28358 100755
--- a/etc/rc.d/ntpd
+++ b/etc/rc.d/ntpd
@@ -14,6 +14,8 @@ name="ntpd"
rcvar="ntpd_enable"
command="/usr/sbin/${name}"
pidfile="/var/run/${name}.pid"
+extra_commands="fetch"
+fetch_cmd="ntpd_fetch_leapfile"
start_precmd="ntpd_precmd"
load_rc_config $name
@@ -30,6 +32,10 @@ ntpd_precmd()
return 0;
fi
+ if [ ! -f $ntp_db_leapfile ]; then
+ ntpd_fetch_leapfile
+ fi
+
# If running in a chroot cage, ensure that the appropriate files
# exist inside the cage, as well as helper symlinks into the cage
# from outside.
@@ -44,10 +50,71 @@ ntpd_precmd()
( cd /dev ; /bin/pax -rw -pe clockctl "${ntpd_chrootdir}/dev" )
fi
ln -fs "${ntpd_chrootdir}/var/db/ntp.drift" /var/db/ntp.drift
+ ln -fs "${ntpd_chrootdir}${ntp_tmp_leapfile}" ${ntp_tmp_leapfile}
# Change run_rc_commands()'s internal copy of $ntpd_flags
#
rc_flags="-u ntpd:ntpd -i ${ntpd_chrootdir} $rc_flags"
}
+current_ntp_ts() {
+ # Seconds between 1900-01-01 and 1970-01-01
+ # echo $(((70*365+17)*86400))
+ ntp_to_unix=2208988800
+
+ echo $(($(date -u +%s)+$ntp_to_unix))
+}
+
+get_ntp_leapfile_ver() {
+ expr "$(awk '$1 == "#$" { print $2 }' "$1" 2>/dev/null)" : \
+ '^\([1-9][0-9]*\)$' \| 0
+}
+
+get_ntp_leapfile_expiry() {
+ expr "$(awk '$1 == "#@" { print $2 }' "$1" 2>/dev/null)" : \
+ '^\([1-9][0-9]*\)$' \| 0
+}
+
+ntpd_fetch_leapfile() {
+ local ntp_tmp_leapfile rc verbose
+
+ if checkyesno ntp_leapfile_fetch_verbose; then
+ verbose=echo
+ else
+ verbose=:
+ fi
+
+ ntp_tmp_leapfile="/var/run/ntpd.leap-seconds.list"
+
+ ntp_ver_no_src=$(get_ntp_leapfile_ver $ntp_src_leapfile)
+ ntp_ver_no_db=$(get_ntp_leapfile_ver $ntp_db_leapfile)
+ $verbose ntp_src_leapfile version is $ntp_ver_no_src
+ $verbose ntp_db_leapfile version is $ntp_ver_no_db
+
+ if [ "$ntp_ver_no_src" -gt "$ntp_ver_no_db" ]; then
+ $verbose replacing $ntp_db_leapfile with $ntp_src_leapfile
+ cp -p $ntp_src_leapfile $ntp_db_leapfile
+ ntp_ver_no_db=$ntp_ver_no_src
+ else
+ $verbose not replacing $ntp_db_leapfile with $ntp_src_leapfile
+ fi
+ ntp_leap_expiry=$(get_ntp_leapfile_expiry $ntp_db_leapfile)
+ ntp_leapfile_expiry_seconds=$((ntp_leapfile_expiry_days*86400))
+ ntp_leap_fetch_date=$((ntp_leap_expiry-ntp_leapfile_expiry_seconds))
+ if [ $(current_ntp_ts) -ge $ntp_leap_fetch_date ]; then
+ $verbose Within ntp leapfile expiry limit, initiating fetch
+ for url in $ntp_leapfile_sources ; do
+ $verbose fetching $url
+ fetch $ntp_leapfile_fetch_opts -o $ntp_tmp_leapfile $url && break
+ done
+ ntp_ver_no_tmp=$(get_ntp_leapfile_ver $ntp_tmp_leapfile)
+ if [ "$ntp_ver_no_tmp" -gt "$ntp_ver_no_db" ]; then
+ $verbose using $url as $ntp_db_leapfile
+ mv $ntp_tmp_leapfile $ntp_db_leapfile
+ else
+ $verbose using existing $ntp_db_leapfile
+ fi
+ fi
+}
+
run_rc_command "$1"
diff --git a/lib/libdevctl/devctl.3 b/lib/libdevctl/devctl.3
index b8a84d4..7c4c74b 100644
--- a/lib/libdevctl/devctl.3
+++ b/lib/libdevctl/devctl.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 26, 2014
+.Dd February 2, 2016
.Dt DEVCTL 3
.Os
.Sh NAME
@@ -33,7 +33,8 @@
.Nm devctl_attach ,
.Nm devctl_detach ,
.Nm devctl_disable ,
-.Nm devctl_enable
+.Nm devctl_enable ,
+.Nm devctl_set_driver
.Nd device control library
.Sh LIBRARY
.Lb libdevctl
@@ -251,4 +252,4 @@ The new device driver failed to attach.
The
.Nm
library first appeared in
-.Fx 11.0 .
+.Fx 10.3 .
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 727419b..7b0722c 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -767,6 +767,8 @@ kinfo_getfile_core(struct procstat_core *core, int *cntp)
eb = buf + len;
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
bp += kf->kf_structsize;
cnt++;
}
@@ -782,6 +784,8 @@ kinfo_getfile_core(struct procstat_core *core, int *cntp)
/* Pass 2: unpack */
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kf, kf->kf_structsize);
/* Advance to next packed record */
@@ -1863,6 +1867,8 @@ kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
eb = buf + len;
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
bp += kv->kve_structsize;
cnt++;
}
@@ -1878,6 +1884,8 @@ kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
/* Pass 2: unpack */
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kv, kv->kve_structsize);
/* Advance to next packed record */
diff --git a/lib/libutil/kinfo_getfile.c b/lib/libutil/kinfo_getfile.c
index 84b64db..8a5477f 100644
--- a/lib/libutil/kinfo_getfile.c
+++ b/lib/libutil/kinfo_getfile.c
@@ -44,6 +44,8 @@ kinfo_getfile(pid_t pid, int *cntp)
eb = buf + len;
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
bp += kf->kf_structsize;
cnt++;
}
@@ -59,6 +61,8 @@ kinfo_getfile(pid_t pid, int *cntp)
/* Pass 2: unpack */
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kf, kf->kf_structsize);
/* Advance to next packed record */
diff --git a/lib/libutil/kinfo_getvmmap.c b/lib/libutil/kinfo_getvmmap.c
index 129aa03..9d9e427 100644
--- a/lib/libutil/kinfo_getvmmap.c
+++ b/lib/libutil/kinfo_getvmmap.c
@@ -44,6 +44,8 @@ kinfo_getvmmap(pid_t pid, int *cntp)
eb = buf + len;
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
bp += kv->kve_structsize;
cnt++;
}
@@ -59,6 +61,8 @@ kinfo_getvmmap(pid_t pid, int *cntp)
/* Pass 2: unpack */
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kv, kv->kve_structsize);
/* Advance to next packed record */
diff --git a/share/man/man5/core.5 b/share/man/man5/core.5
index e8a1653..a5fefc0 100644
--- a/share/man/man5/core.5
+++ b/share/man/man5/core.5
@@ -32,7 +32,7 @@
.\" @(#)core.5 8.3 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd November 22, 2012
+.Dd October 5, 2015
.Dt CORE 5
.Os
.Sh NAME
@@ -126,6 +126,29 @@ Core files will have the suffix
.Em .gz
appended to them.
.El
+.Sh NOTES
+Corefiles are written with open file descriptor information as an ELF note.
+By default, file paths are packed to only use as much space as needed.
+However, file paths can change at any time, including during core dump,
+and this can result in truncated file descriptor data.
+.Pp
+All file descriptor information can be preserved by disabling packing.
+This potentially wastes up to PATH_MAX bytes per open fd.
+Packing is disabled with
+.Dl sysctl kern.coredump_pack_fileinfo=0 .
+.Pp
+Similarly, corefiles are written with vmmap information as an ELF note, which
+contains file paths.
+By default, they are packed to only use as much space as
+needed.
+By the same mechanism as for the open files note, these paths can also
+change at any time and result in a truncated note.
+.Pp
+All vmmap information can be preserved by disabling packing.
+Like the file information, this potentially wastes up to PATH_MAX bytes per
+mapped object.
+Packing is disabled with
+.Dl sysctl kern.coredump_pack_vmmapinfo=0 .
.Sh EXAMPLES
In order to store all core images in per-user private areas under
.Pa /var/coredumps ,
diff --git a/sys/boot/arm/at91/boot2/boot2.c b/sys/boot/arm/at91/boot2/boot2.c
index c3629a5..0388548 100644
--- a/sys/boot/arm/at91/boot2/boot2.c
+++ b/sys/boot/arm/at91/boot2/boot2.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2008 John Hay
- * Copyright (c) 2006 Warner Losh
+ * Copyright (c) 2006 M Warner Losh <imp@freebsd.org>
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
@@ -30,52 +30,16 @@ __FBSDID("$FreeBSD$");
#include "lib.h"
#include "board.h"
+#include "paths.h"
+#include "rbx.h"
-#define RBX_ASKNAME 0x0 /* -a */
-#define RBX_SINGLE 0x1 /* -s */
-/* 0x2 is reserved for log2(RB_NOSYNC). */
-/* 0x3 is reserved for log2(RB_HALT). */
-/* 0x4 is reserved for log2(RB_INITNAME). */
-#define RBX_DFLTROOT 0x5 /* -r */
-/* #define RBX_KDB 0x6 -d */
-/* 0x7 is reserved for log2(RB_RDONLY). */
-/* 0x8 is reserved for log2(RB_DUMP). */
-/* 0x9 is reserved for log2(RB_MINIROOT). */
-#define RBX_CONFIG 0xa /* -c */
-#define RBX_VERBOSE 0xb /* -v */
-/* #define RBX_SERIAL 0xc -h */
-/* #define RBX_CDROM 0xd -C */
-/* 0xe is reserved for log2(RB_POWEROFF). */
-#define RBX_GDB 0xf /* -g */
-/* #define RBX_MUTE 0x10 -m */
-/* 0x11 is reserved for log2(RB_SELFTEST). */
-/* 0x12 is reserved for boot programs. */
-/* 0x13 is reserved for boot programs. */
-/* #define RBX_PAUSE 0x14 -p */
-/* #define RBX_QUIET 0x15 -q */
-#define RBX_NOINTR 0x1c /* -n */
-/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
-/* #define RBX_DUAL 0x1d -D */
-/* 0x1f is reserved for log2(RB_BOOTINFO). */
-
-/* pass: -a, -s, -r, -v, -g */
-#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \
- OPT_SET(RBX_DFLTROOT) | \
- OPT_SET(RBX_VERBOSE) | \
- OPT_SET(RBX_GDB))
-
-#define PATH_DOTCONFIG "/boot.config"
-#define PATH_CONFIG "/boot/config"
-//#define PATH_KERNEL "/boot/kernel/kernel"
+#undef PATH_KERNEL
#define PATH_KERNEL "/boot/kernel/kernel.gz.tramp"
extern uint32_t _end;
#define NOPT 6
-#define OPT_SET(opt) (1 << (opt))
-#define OPT_CHECK(opt) ((opts) & OPT_SET(opt))
-
static const char optstr[NOPT] = "agnrsv";
static const unsigned char flags[NOPT] = {
RBX_ASKNAME,
diff --git a/sys/boot/arm/ixp425/boot2/boot2.c b/sys/boot/arm/ixp425/boot2/boot2.c
index e5f4982..93c4fe1 100644
--- a/sys/boot/arm/ixp425/boot2/boot2.c
+++ b/sys/boot/arm/ixp425/boot2/boot2.c
@@ -28,51 +28,13 @@ __FBSDID("$FreeBSD$");
#include <stdarg.h>
#include "lib.h"
-
-#define RBX_ASKNAME 0x0 /* -a */
-#define RBX_SINGLE 0x1 /* -s */
-/* 0x2 is reserved for log2(RB_NOSYNC). */
-/* 0x3 is reserved for log2(RB_HALT). */
-/* 0x4 is reserved for log2(RB_INITNAME). */
-#define RBX_DFLTROOT 0x5 /* -r */
-/* #define RBX_KDB 0x6 -d */
-/* 0x7 is reserved for log2(RB_RDONLY). */
-/* 0x8 is reserved for log2(RB_DUMP). */
-/* 0x9 is reserved for log2(RB_MINIROOT). */
-#define RBX_CONFIG 0xa /* -c */
-#define RBX_VERBOSE 0xb /* -v */
-/* #define RBX_SERIAL 0xc -h */
-/* #define RBX_CDROM 0xd -C */
-/* 0xe is reserved for log2(RB_POWEROFF). */
-#define RBX_GDB 0xf /* -g */
-/* #define RBX_MUTE 0x10 -m */
-/* 0x11 is reserved for log2(RB_SELFTEST). */
-/* 0x12 is reserved for boot programs. */
-/* 0x13 is reserved for boot programs. */
-/* #define RBX_PAUSE 0x14 -p */
-/* #define RBX_QUIET 0x15 -q */
-#define RBX_NOINTR 0x1c /* -n */
-/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
-/* #define RBX_DUAL 0x1d -D */
-/* 0x1f is reserved for log2(RB_BOOTINFO). */
-
-/* pass: -a, -s, -r, -v, -g */
-#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \
- OPT_SET(RBX_DFLTROOT) | \
- OPT_SET(RBX_VERBOSE) | \
- OPT_SET(RBX_GDB))
-
-#define PATH_DOTCONFIG "/boot.config"
-#define PATH_CONFIG "/boot/config"
-#define PATH_KERNEL "/boot/kernel/kernel"
+#include "paths.h"
+#include "rbx.h"
extern uint32_t _end;
#define NOPT 6
-#define OPT_SET(opt) (1 << (opt))
-#define OPT_CHECK(opt) ((opts) & OPT_SET(opt))
-
static const char optstr[NOPT] = "agnrsv";
static const unsigned char flags[NOPT] = {
RBX_ASKNAME,
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index 6a88e39..e352ef7 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -856,7 +856,7 @@ __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md));
if (error == EOPNOTSUPP) {
md.md_cval += ef->off;
- md.md_data = (void *)((uintptr_t)md.md_data + ef->off);
+ md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off);
} else if (error != 0)
return (error);
#endif
diff --git a/sys/boot/common/paths.h b/sys/boot/common/paths.h
new file mode 100644
index 0000000..9ed45e6
--- /dev/null
+++ b/sys/boot/common/paths.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2016 M. Warner Losh <imp@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _PATHS_H_
+#define _PATHS_H_
+
+#define PATH_DOTCONFIG "/boot.config"
+#define PATH_CONFIG "/boot/config"
+#define PATH_LOADER "/boot/loader"
+#define PATH_LOADER_EFI "/boot/loader.efi"
+#define PATH_LOADER_ZFS "/boot/zfsloader"
+#define PATH_KERNEL "/boot/kernel/kernel"
+
+#endif /* _PATHS_H_ */
diff --git a/sys/boot/i386/common/rbx.h b/sys/boot/common/rbx.h
index 21371a5..21371a5 100644
--- a/sys/boot/i386/common/rbx.h
+++ b/sys/boot/common/rbx.h
diff --git a/sys/boot/efi/Makefile b/sys/boot/efi/Makefile
index acf5a49..89a3576 100644
--- a/sys/boot/efi/Makefile
+++ b/sys/boot/efi/Makefile
@@ -11,5 +11,9 @@ SUBDIR+= libefi loader boot1
.endif # ${COMPILER_TYPE} != "gcc"
+.if ${MACHINE_CPUARCH} == "ia64"
+SUBDIR+= libefi
+.endif
+
.include <bsd.subdir.mk>
diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c
index f046235..1161b0a 100644
--- a/sys/boot/efi/boot1/boot1.c
+++ b/sys/boot/efi/boot1/boot1.c
@@ -31,8 +31,7 @@ __FBSDID("$FreeBSD$");
#include <eficonsctl.h>
#include "boot_module.h"
-
-#define _PATH_LOADER "/boot/loader.efi"
+#include "paths.h"
static const boot_module_t *boot_modules[] =
{
@@ -51,9 +50,6 @@ static const boot_module_t *boot_modules[] =
void putchar(int c);
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
-static void try_load(const boot_module_t* mod);
-static EFI_STATUS probe_handle(EFI_HANDLE h);
-
EFI_SYSTEM_TABLE *systab;
EFI_BOOT_SERVICES *bs;
static EFI_HANDLE *image;
@@ -86,57 +82,489 @@ Free(void *buf, const char *file __unused, int line __unused)
}
/*
- * This function only returns if it fails to load the kernel. If it
- * succeeds, it simply boots the kernel.
+ * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
+ * FALSE otherwise.
*/
-void
-try_load(const boot_module_t *mod)
+static BOOLEAN
+nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+ int len;
+
+ if (imgpath == NULL || imgpath->Type != devpath->Type ||
+ imgpath->SubType != devpath->SubType)
+ return (FALSE);
+
+ len = DevicePathNodeLength(imgpath);
+ if (len != DevicePathNodeLength(devpath))
+ return (FALSE);
+
+ return (memcmp(imgpath, devpath, (size_t)len) == 0);
+}
+
+/*
+ * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
+ * in imgpath and devpath match up to their respect occurances of a media
+ * node, FALSE otherwise.
+ */
+static BOOLEAN
+device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+
+ if (imgpath == NULL)
+ return (FALSE);
+
+ while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
+ if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
+ IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
+ return (TRUE);
+
+ if (!nodes_match(imgpath, devpath))
+ return (FALSE);
+
+ imgpath = NextDevicePathNode(imgpath);
+ devpath = NextDevicePathNode(devpath);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * devpath_last returns the last non-path end node in devpath.
+ */
+static EFI_DEVICE_PATH *
+devpath_last(EFI_DEVICE_PATH *devpath)
+{
+
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
+
+ return (devpath);
+}
+
+/*
+ * devpath_node_str is a basic output method for a devpath node which
+ * only understands a subset of the available sub types.
+ *
+ * If we switch to UEFI 2.x then we should update it to use:
+ * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
+ */
+static int
+devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+
+ switch (devpath->Type) {
+ case MESSAGING_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MSG_ATAPI_DP: {
+ ATAPI_DEVICE_PATH *atapi;
+
+ atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "ata(%s,%s,0x%x)",
+ (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
+ (atapi->SlaveMaster == 1) ? "Slave" : "Master",
+ atapi->Lun);
+ }
+ case MSG_USB_DP: {
+ USB_DEVICE_PATH *usb;
+
+ usb = (USB_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "usb(0x%02x,0x%02x)",
+ usb->ParentPortNumber, usb->InterfaceNumber);
+ }
+ case MSG_SCSI_DP: {
+ SCSI_DEVICE_PATH *scsi;
+
+ scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
+ scsi->Pun, scsi->Lun);
+ }
+ case MSG_SATA_DP: {
+ SATA_DEVICE_PATH *sata;
+
+ sata = (SATA_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
+ sata->HBAPortNumber, sata->PortMultiplierPortNumber,
+ sata->Lun);
+ }
+ default:
+ return snprintf(buf, size, "msg(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case HARDWARE_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case HW_PCI_DP: {
+ PCI_DEVICE_PATH *pci;
+
+ pci = (PCI_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "pci(0x%02x,0x%02x)",
+ pci->Device, pci->Function);
+ }
+ default:
+ return snprintf(buf, size, "hw(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case ACPI_DEVICE_PATH: {
+ ACPI_HID_DEVICE_PATH *acpi;
+
+ acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
+ if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ switch (EISA_ID_TO_NUM(acpi->HID)) {
+ case 0x0a03:
+ return snprintf(buf, size, "pciroot(0x%x)",
+ acpi->UID);
+ case 0x0a08:
+ return snprintf(buf, size, "pcieroot(0x%x)",
+ acpi->UID);
+ case 0x0604:
+ return snprintf(buf, size, "floppy(0x%x)",
+ acpi->UID);
+ case 0x0301:
+ return snprintf(buf, size, "keyboard(0x%x)",
+ acpi->UID);
+ case 0x0501:
+ return snprintf(buf, size, "serial(0x%x)",
+ acpi->UID);
+ case 0x0401:
+ return snprintf(buf, size, "parallelport(0x%x)",
+ acpi->UID);
+ default:
+ return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
+ EISA_ID_TO_NUM(acpi->HID), acpi->UID);
+ }
+ }
+
+ return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
+ acpi->UID);
+ }
+ case MEDIA_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MEDIA_CDROM_DP: {
+ CDROM_DEVICE_PATH *cdrom;
+
+ cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "cdrom(%x)",
+ cdrom->BootEntry);
+ }
+ case MEDIA_HARDDRIVE_DP: {
+ HARDDRIVE_DEVICE_PATH *hd;
+
+ hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "hd(%x)",
+ hd->PartitionNumber);
+ }
+ default:
+ return snprintf(buf, size, "media(0x%02x)",
+ devpath->SubType);
+ }
+ case BBS_DEVICE_PATH:
+ return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
+ case END_DEVICE_PATH_TYPE:
+ return (0);
+ }
+
+ return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
+ devpath->SubType);
+}
+
+/*
+ * devpath_strlcat appends a text description of devpath to buf but not more
+ * than size - 1 characters followed by NUL-terminator.
+ */
+int
+devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+ size_t len, used;
+ const char *sep;
+
+ sep = "";
+ used = 0;
+ while (!IsDevicePathEnd(devpath)) {
+ len = snprintf(buf, size - used, "%s", sep);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+
+ len = devpath_node_str(buf, size - used, devpath);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+ devpath = NextDevicePathNode(devpath);
+ sep = ":";
+ }
+
+ return (used);
+}
+
+/*
+ * devpath_str is convenience method which returns the text description of
+ * devpath using a static buffer, so it isn't thread safe!
+ */
+char *
+devpath_str(EFI_DEVICE_PATH *devpath)
{
- size_t bufsize;
- void *buf;
+ static char buf[256];
+
+ devpath_strlcat(buf, sizeof(buf), devpath);
+
+ return buf;
+}
+
+/*
+ * load_loader attempts to load the loader image data.
+ *
+ * It tries each module and its respective devices, identified by mod->probe,
+ * in order until a successful load occurs at which point it returns EFI_SUCCESS
+ * and EFI_NOT_FOUND otherwise.
+ *
+ * Only devices which have preferred matching the preferred parameter are tried.
+ */
+static EFI_STATUS
+load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
+ size_t *bufsize, BOOLEAN preferred)
+{
+ UINTN i;
dev_info_t *dev;
+ const boot_module_t *mod;
+
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+ mod = boot_modules[i];
+ for (dev = mod->devices(); dev != NULL; dev = dev->next) {
+ if (dev->preferred != preferred)
+ continue;
+
+ if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *devinfop = dev;
+ *modp = mod;
+ return (EFI_SUCCESS);
+ }
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+/*
+ * try_boot only returns if it fails to load the loader. If it succeeds
+ * it simply boots, otherwise it returns the status of last EFI call.
+ */
+static EFI_STATUS
+try_boot()
+{
+ size_t bufsize, loadersize, cmdsize;
+ void *buf, *loaderbuf;
+ char *cmd;
+ dev_info_t *dev;
+ const boot_module_t *mod;
EFI_HANDLE loaderhandle;
EFI_LOADED_IMAGE *loaded_image;
EFI_STATUS status;
- status = mod->load(_PATH_LOADER, &dev, &buf, &bufsize);
- if (status == EFI_NOT_FOUND)
- return;
-
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
if (status != EFI_SUCCESS) {
- printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER,
- EFI_ERROR_CODE(status));
- return;
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
+ FALSE);
+ if (status != EFI_SUCCESS) {
+ printf("Failed to load '%s'\n", PATH_LOADER_EFI);
+ return (status);
+ }
}
- if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
- &loaderhandle)) != EFI_SUCCESS) {
+ /*
+ * Read in and parse the command line from /boot.config or /boot/config,
+ * if present. We'll pass it the next stage via a simple ASCII
+ * string. loader.efi has a hack for ASCII strings, so we'll use that to
+ * keep the size down here. We only try to read the alternate file if
+ * we get EFI_NOT_FOUND because all other errors mean that the boot_module
+ * had troubles with the filesystem. We could return early, but we'll let
+ * loading the actual kernel sort all that out. Since these files are
+ * optional, we don't report errors in trying to read them.
+ */
+ cmd = NULL;
+ cmdsize = 0;
+ status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
+ if (status == EFI_NOT_FOUND)
+ status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
+ if (status == EFI_SUCCESS) {
+ cmdsize = bufsize + 1;
+ cmd = malloc(cmdsize);
+ if (cmd == NULL)
+ goto errout;
+ memcpy(cmd, buf, bufsize);
+ cmd[bufsize] = '\0';
+ free(buf);
+ buf = NULL;
+ }
+
+ if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
+ loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
mod->name, bufsize, EFI_ERROR_CODE(status));
- return;
+ goto errout;
}
if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
(VOID**)&loaded_image)) != EFI_SUCCESS) {
printf("Failed to query LoadedImage provided by %s (%lu)\n",
mod->name, EFI_ERROR_CODE(status));
- return;
+ goto errout;
}
+ if (cmd != NULL)
+ printf(" command args: %s\n", cmd);
+
loaded_image->DeviceHandle = dev->devhandle;
+ loaded_image->LoadOptionsSize = cmdsize;
+ loaded_image->LoadOptions = cmd;
+
+ DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".\n");
if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
EFI_SUCCESS) {
printf("Failed to start image provided by %s (%lu)\n",
mod->name, EFI_ERROR_CODE(status));
- return;
+ loaded_image->LoadOptionsSize = 0;
+ loaded_image->LoadOptions = NULL;
}
+
+errout:
+ if (cmd != NULL)
+ free(cmd);
+ if (buf != NULL)
+ free(buf);
+ if (loaderbuf != NULL)
+ free(loaderbuf);
+
+ return (status);
+}
+
+/*
+ * probe_handle determines if the passed handle represents a logical partition
+ * if it does it uses each module in order to probe it and if successful it
+ * returns EFI_SUCCESS.
+ */
+static EFI_STATUS
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
+{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath;
+ EFI_STATUS status;
+ UINTN i;
+
+ /* Figure out if we're dealing with an actual partition. */
+ status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ DPRINTF("probing: %s\n", devpath_str(devpath));
+
+ status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ if (!blkio->Media->LogicalPartition)
+ return (EFI_UNSUPPORTED);
+
+ *preferred = device_paths_match(imgpath, devpath);
+
+ /* Run through each module, see if it can load this partition */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+
+ if ((status = bs->AllocatePool(EfiLoaderData,
+ sizeof(*devinfo), (void **)&devinfo)) !=
+ EFI_SUCCESS) {
+ DPRINTF("\nFailed to allocate devinfo (%lu)\n",
+ EFI_ERROR_CODE(status));
+ continue;
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->devdata = NULL;
+ devinfo->preferred = *preferred;
+ devinfo->next = NULL;
+
+ status = boot_modules[i]->probe(devinfo);
+ if (status == EFI_SUCCESS)
+ return (EFI_SUCCESS);
+ (void)bs->FreePool(devinfo);
+ }
+
+ return (EFI_UNSUPPORTED);
+}
+
+/*
+ * probe_handle_status calls probe_handle and outputs the returned status
+ * of the call.
+ */
+static void
+probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
+{
+ EFI_STATUS status;
+ BOOLEAN preferred;
+
+ status = probe_handle(h, imgpath, &preferred);
+
+ DPRINTF("probe: ");
+ switch (status) {
+ case EFI_UNSUPPORTED:
+ printf(".");
+ DPRINTF(" not supported\n");
+ break;
+ case EFI_SUCCESS:
+ if (preferred) {
+ printf("%c", '*');
+ DPRINTF(" supported (preferred)\n");
+ } else {
+ printf("%c", '+');
+ DPRINTF(" supported\n");
+ }
+ break;
+ default:
+ printf("x");
+ DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
+ break;
+ }
+ DSTALL(500000);
}
EFI_STATUS
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
{
EFI_HANDLE *handles;
+ EFI_LOADED_IMAGE *img;
+ EFI_DEVICE_PATH *imgpath;
EFI_STATUS status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
@@ -174,7 +602,7 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
conout->ClearScreen(conout);
printf("\n>> FreeBSD EFI boot block\n");
- printf(" Loader path: %s\n\n", _PATH_LOADER);
+ printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
printf(" Initializing modules:");
for (i = 0; i < NUM_BOOT_MODULES; i++) {
if (boot_modules[i] == NULL)
@@ -219,20 +647,22 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
/* Scan all partitions, probing with all modules. */
nhandles = hsize / sizeof(*handles);
printf(" Probing %zu block devices...", nhandles);
- for (i = 0; i < nhandles; i++) {
- status = probe_handle(handles[i]);
- switch (status) {
- case EFI_UNSUPPORTED:
- printf(".");
- break;
- case EFI_SUCCESS:
- printf("+");
- break;
- default:
- printf("x");
- break;
- }
+ DPRINTF("\n");
+
+ /* Determine the devpath of our image so we can prefer it. */
+ status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
+ imgpath = NULL;
+ if (status == EFI_SUCCESS) {
+ status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
+ (void **)&imgpath);
+ if (status != EFI_SUCCESS)
+ DPRINTF("Failed to get image DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
}
+
+ for (i = 0; i < nhandles; i++)
+ probe_handle_status(handles[i], imgpath);
printf(" done\n");
/* Status summary. */
@@ -243,78 +673,15 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
}
}
- /* Select a partition to boot by trying each module in order. */
- for (i = 0; i < NUM_BOOT_MODULES; i++)
- if (boot_modules[i] != NULL)
- try_load(boot_modules[i]);
+ try_boot();
/* If we get here, we're out of luck... */
panic("No bootable partitions found!");
}
-static EFI_STATUS
-probe_handle(EFI_HANDLE h)
-{
- dev_info_t *devinfo;
- EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath;
- EFI_STATUS status;
- UINTN i;
-
- /* Figure out if we're dealing with an actual partition. */
- status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
- if (status == EFI_UNSUPPORTED)
- return (status);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query DevicePath (%lu)\n",
- EFI_ERROR_CODE(status));
- return (status);
- }
-
- while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
- devpath = NextDevicePathNode(devpath);
-
- status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
- if (status == EFI_UNSUPPORTED)
- return (status);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
- EFI_ERROR_CODE(status));
- return (status);
- }
-
- if (!blkio->Media->LogicalPartition)
- return (EFI_UNSUPPORTED);
-
- /* Run through each module, see if it can load this partition */
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- if (boot_modules[i] == NULL)
- continue;
-
- if ((status = bs->AllocatePool(EfiLoaderData,
- sizeof(*devinfo), (void **)&devinfo)) !=
- EFI_SUCCESS) {
- DPRINTF("\nFailed to allocate devinfo (%lu)\n",
- EFI_ERROR_CODE(status));
- continue;
- }
- devinfo->dev = blkio;
- devinfo->devpath = devpath;
- devinfo->devhandle = h;
- devinfo->devdata = NULL;
- devinfo->next = NULL;
-
- status = boot_modules[i]->probe(devinfo);
- if (status == EFI_SUCCESS)
- return (EFI_SUCCESS);
- (void)bs->FreePool(devinfo);
- }
-
- return (EFI_UNSUPPORTED);
-}
-
+/*
+ * add_device adds a device to the passed devinfo list.
+ */
void
add_device(dev_info_t **devinfop, dev_info_t *devinfo)
{
diff --git a/sys/boot/efi/boot1/boot_module.h b/sys/boot/efi/boot1/boot_module.h
index 2c158f6..296d5a6 100644
--- a/sys/boot/efi/boot1/boot_module.h
+++ b/sys/boot/efi/boot1/boot_module.h
@@ -36,9 +36,11 @@
#include <eficonsctl.h>
#ifdef EFI_DEBUG
-#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#define DPRINTF(fmt, args...) printf(fmt, ##args)
+#define DSTALL(d) bs->Stall(d)
#else
#define DPRINTF(fmt, ...) {}
+#define DSTALL(d) {}
#endif
/* EFI device info */
@@ -48,6 +50,7 @@ typedef struct dev_info
EFI_DEVICE_PATH *devpath;
EFI_HANDLE *devhandle;
void *devdata;
+ BOOLEAN preferred;
struct dev_info *next;
} dev_info_t;
@@ -75,19 +78,21 @@ typedef struct boot_module_t
/*
* load should select the best out of a set of devices that probe
- * indicated were loadable and load it.
+ * indicated were loadable and load the specified file.
*
* Return codes:
* EFI_SUCCESS = The module can handle the device.
* EFI_NOT_FOUND = The module can not handle the device.
* Other = The module encountered an error.
*/
- EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo,
+ EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo,
void **buf, size_t *bufsize);
/* status outputs information about the probed devices. */
void (*status)();
+ /* valid devices as found by probe. */
+ dev_info_t *(*devices)();
} boot_module_t;
/* Standard boot modules. */
@@ -107,4 +112,6 @@ extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
extern EFI_SYSTEM_TABLE *systab;
extern EFI_BOOT_SERVICES *bs;
+extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath);
+extern char *devpath_str(EFI_DEVICE_PATH *devpath);
#endif
diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c
index 07c7152..63087ea 100644
--- a/sys/boot/efi/boot1/ufs_module.c
+++ b/sys/boot/efi/boot1/ufs_module.c
@@ -93,7 +93,7 @@ probe(dev_info_t* dev)
}
static EFI_STATUS
-try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
+load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
{
ufs_ino_t ino;
EFI_STATUS status;
@@ -101,59 +101,46 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
ssize_t read;
void *buf;
- if (init_dev(dev) < 0)
+ DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath));
+
+ if (init_dev(dev) < 0) {
+ DPRINTF("Failed to init device\n");
return (EFI_UNSUPPORTED);
+ }
- if ((ino = lookup(loader_path)) == 0)
+ if ((ino = lookup(filepath)) == 0) {
+ DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath);
return (EFI_NOT_FOUND);
+ }
if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
- printf("Failed to read size of '%s' ino: %d\n", loader_path,
- ino);
+ printf("Failed to read size of '%s' ino: %d\n", filepath, ino);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
EFI_SUCCESS) {
- printf("Failed to allocate read buffer (%lu)\n",
- EFI_ERROR_CODE(status));
+ printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
+ size, filepath, EFI_ERROR_CODE(status));
return (status);
}
read = fsread(ino, buf, size);
if ((size_t)read != size) {
- printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read,
+ printf("Failed to read '%s' (%zd != %zu)\n", filepath, read,
size);
(void)bs->FreePool(buf);
return (EFI_INVALID_PARAMETER);
}
+ DPRINTF("Load complete\n");
+
*bufp = buf;
*bufsize = size;
return (EFI_SUCCESS);
}
-static EFI_STATUS
-load(const char *loader_path, dev_info_t **devinfop, void **buf,
- size_t *bufsize)
-{
- dev_info_t *dev;
- EFI_STATUS status;
-
- for (dev = devices; dev != NULL; dev = dev->next) {
- status = try_load(dev, loader_path, buf, bufsize);
- if (status == EFI_SUCCESS) {
- *devinfop = dev;
- return (EFI_SUCCESS);
- } else if (status != EFI_NOT_FOUND) {
- return (status);
- }
- }
-
- return (EFI_NOT_FOUND);
-}
-
static void
status()
{
@@ -176,10 +163,18 @@ status()
}
}
+static dev_info_t *
+_devices()
+{
+
+ return (devices);
+}
+
const boot_module_t ufs_module =
{
.name = "UFS",
.probe = probe,
.load = load,
- .status = status
+ .status = status,
+ .devices = _devices
};
diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c
index 96eec33..925f0b2 100644
--- a/sys/boot/efi/boot1/zfs_module.c
+++ b/sys/boot/efi/boot1/zfs_module.c
@@ -91,7 +91,7 @@ probe(dev_info_t *dev)
}
static EFI_STATUS
-try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize)
+load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
{
spa_t *spa;
struct zfsmount zfsmount;
@@ -102,32 +102,41 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs
EFI_STATUS status;
spa = devinfo->devdata;
- if (zfs_spa_init(spa) != 0) {
- /* Init failed, don't report this loudly. */
+
+ DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name,
+ devpath_str(devinfo->devpath));
+
+ if ((err = zfs_spa_init(spa)) != 0) {
+ DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
- if (zfs_mount(spa, 0, &zfsmount) != 0) {
- /* Mount failed, don't report this loudly. */
+ if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
+ DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
- if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) {
- printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
+ if (err == ENOENT) {
+ DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
+ filepath, spa->spa_name, err);
+ return (EFI_NOT_FOUND);
+ }
+ printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
- printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
!= EFI_SUCCESS) {
- printf("Failed to allocate load buffer for pool %s (%lu)\n",
- spa->spa_name, EFI_ERROR_CODE(status));
+ printf("Failed to allocate load buffer %zd for pool '%s' for '%s' "
+ "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
return (EFI_INVALID_PARAMETER);
}
@@ -144,26 +153,6 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs
return (EFI_SUCCESS);
}
-static EFI_STATUS
-load(const char *loader_path, dev_info_t **devinfop, void **bufp,
- size_t *bufsize)
-{
- dev_info_t *devinfo;
- EFI_STATUS status;
-
- for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) {
- status = try_load(devinfo, loader_path, bufp, bufsize);
- if (status == EFI_SUCCESS) {
- *devinfop = devinfo;
- return (EFI_SUCCESS);
- } else if (status != EFI_NOT_FOUND) {
- return (status);
- }
- }
-
- return (EFI_NOT_FOUND);
-}
-
static void
status()
{
@@ -189,11 +178,19 @@ init()
zfs_init();
}
+static dev_info_t *
+_devices()
+{
+
+ return (devices);
+}
+
const boot_module_t zfs_module =
{
.name = "ZFS",
.init = init,
.probe = probe,
.load = load,
- .status = status
+ .status = status,
+ .devices = _devices
};
diff --git a/sys/boot/efi/include/efidevp.h b/sys/boot/efi/include/efidevp.h
index f0f49ef..dda79de7 100644
--- a/sys/boot/efi/include/efidevp.h
+++ b/sys/boot/efi/include/efidevp.h
@@ -40,9 +40,7 @@ typedef struct _EFI_DEVICE_PATH {
#define EFI_DP_TYPE_MASK 0x7F
#define EFI_DP_TYPE_UNPACKED 0x80
-//#define END_DEVICE_PATH_TYPE 0xff
#define END_DEVICE_PATH_TYPE 0x7f
-//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
@@ -56,8 +54,8 @@ typedef struct _EFI_DEVICE_PATH {
#define DevicePathSubType(a) ( (a)->SubType )
#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) )
#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a)))
-//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED )
-#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE )
+#define IsDevicePathType(a, t) ( DevicePathType(a) == t )
+#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE)
#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) )
#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED )
@@ -285,6 +283,13 @@ typedef struct _UART_DEVICE_PATH {
#define DEVICE_PATH_MESSAGING_VT_UTF8 \
{ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} }
+#define MSG_SATA_DP 0x12
+typedef struct _SATA_DEVICE_PATH {
+ EFI_DEVICE_PATH Header;
+ UINT16 HBAPortNumber;
+ UINT16 PortMultiplierPortNumber;
+ UINT16 Lun;
+} SATA_DEVICE_PATH;
#define MEDIA_DEVICE_PATH 0x04
diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile
index f87fbe9..880547e 100644
--- a/sys/boot/efi/libefi/Makefile
+++ b/sys/boot/efi/libefi/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= efi
INTERNALLIB=
WARNS?= 2
@@ -7,6 +9,10 @@ WARNS?= 2
SRCS= delay.c efi_console.c efinet.c efipart.c errno.c handles.c \
libefi.c time.c
+.if ${MACHINE_CPUARCH} == "ia64"
+IGNORE_PRAGMA= 1
+.endif
+
.if ${MACHINE_ARCH} == "amd64"
CFLAGS+= -fPIC -mno-red-zone
.endif
diff --git a/sys/boot/efi/libefi/libefi.c b/sys/boot/efi/libefi/libefi.c
index f87b89a..c76bd6c 100644
--- a/sys/boot/efi/libefi/libefi.c
+++ b/sys/boot/efi/libefi/libefi.c
@@ -44,7 +44,7 @@ static CHAR16 *
arg_skipsep(CHAR16 *argp)
{
- while (*argp == ' ' || *argp == '\t')
+ while (*argp == ' ' || *argp == '\t' || *argp == '\n')
argp++;
return (argp);
}
@@ -53,7 +53,7 @@ static CHAR16 *
arg_skipword(CHAR16 *argp)
{
- while (*argp && *argp != ' ' && *argp != '\t')
+ while (*argp && *argp != ' ' && *argp != '\t' && *argp != '\n')
argp++;
return (argp);
}
diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c
index a90a87e..d167af2 100644
--- a/sys/boot/efi/loader/main.c
+++ b/sys/boot/efi/loader/main.c
@@ -29,6 +29,8 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/boot.h>
#include <stand.h>
#include <string.h>
#include <setjmp.h>
@@ -63,6 +65,7 @@ EFI_GUID dxe = DXE_SERVICES_TABLE_GUID;
EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
+EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
#ifdef EFI_ZFS_BOOT
static void efi_zfs_probe(void);
@@ -82,16 +85,108 @@ print_str16(const CHAR16 *str)
printf("%c", (char)str[i]);
}
+static void
+cp16to8(const CHAR16 *src, char *dst, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len && src[i]; i++)
+ dst[i] = (char)src[i];
+}
+
+static int
+has_keyboard(void)
+{
+ EFI_STATUS status;
+ EFI_DEVICE_PATH *path;
+ EFI_HANDLE *hin, *hin_end, *walker;
+ UINTN sz;
+ int retval = 0;
+
+ /*
+ * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
+ * do the typical dance to get the right sized buffer.
+ */
+ sz = 0;
+ hin = NULL;
+ status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, 0);
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ hin = (EFI_HANDLE *)malloc(sz);
+ status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz,
+ hin);
+ if (EFI_ERROR(status))
+ free(hin);
+ }
+ if (EFI_ERROR(status))
+ return retval;
+
+ /*
+ * Look at each of the handles. If it supports the device path protocol,
+ * use it to get the device path for this handle. Then see if that
+ * device path matches either the USB device path for keyboards or the
+ * legacy device path for keyboards.
+ */
+ hin_end = &hin[sz / sizeof(*hin)];
+ for (walker = hin; walker < hin_end; walker++) {
+ status = BS->HandleProtocol(*walker, &devid, (VOID **)&path);
+ if (EFI_ERROR(status))
+ continue;
+
+ while (!IsDevicePathEnd(path)) {
+ /*
+ * Check for the ACPI keyboard node. All PNP3xx nodes
+ * are keyboards of different flavors. Note: It is
+ * unclear of there's always a keyboard node when
+ * there's a keyboard controller, or if there's only one
+ * when a keyboard is detected at boot.
+ */
+ if (DevicePathType(path) == ACPI_DEVICE_PATH &&
+ (DevicePathSubType(path) == ACPI_DP ||
+ DevicePathSubType(path) == ACPI_EXTENDED_DP)) {
+ ACPI_HID_DEVICE_PATH *acpi;
+
+ acpi = (ACPI_HID_DEVICE_PATH *)(void *)path;
+ if ((EISA_ID_TO_NUM(acpi->HID) & 0xff00) == 0x300 &&
+ (acpi->HID & 0xffff) == PNP_EISA_ID_CONST) {
+ retval = 1;
+ goto out;
+ }
+ /*
+ * Check for USB keyboard node, if present. Unlike a
+ * PS/2 keyboard, these definitely only appear when
+ * connected to the system.
+ */
+ } else if (DevicePathType(path) == MESSAGING_DEVICE_PATH &&
+ DevicePathSubType(path) == MSG_USB_CLASS_DP) {
+ USB_CLASS_DEVICE_PATH *usb;
+
+ usb = (USB_CLASS_DEVICE_PATH *)(void *)path;
+ if (usb->DeviceClass == 3 && /* HID */
+ usb->DeviceSubClass == 1 && /* Boot devices */
+ usb->DeviceProtocol == 1) { /* Boot keyboards */
+ retval = 1;
+ goto out;
+ }
+ }
+ path = NextDevicePathNode(path);
+ }
+ }
+out:
+ free(hin);
+ return retval;
+}
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
char var[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i, j, vargood, unit;
+ int i, j, vargood, unit, howto;
struct devsw *dev;
uint64_t pool_guid;
UINTN k;
+ int has_kbd;
archsw.arch_autoload = efi_autoload;
archsw.arch_getdev = efi_getdev;
@@ -103,6 +198,8 @@ main(int argc, CHAR16 *argv[])
archsw.arch_zfs_probe = efi_zfs_probe;
#endif
+ has_kbd = has_keyboard();
+
/*
* XXX Chicken-and-egg problem; we want to have console output
* early, but some console attributes may depend on reading from
@@ -112,27 +209,101 @@ main(int argc, CHAR16 *argv[])
cons_probe();
/*
+ * Parse the args to set the console settings, etc
+ * boot1.efi passes these in, if it can read /boot.config or /boot/config
+ * or iPXE may be setup to pass these in.
+ *
* Loop through the args, and for each one that contains an '=' that is
* not the first character, add it to the environment. This allows
* loader and kernel env vars to be passed on the command line. Convert
* args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
*/
+ howto = 0;
for (i = 1; i < argc; i++) {
- vargood = 0;
- for (j = 0; argv[i][j] != 0; j++) {
- if (j == sizeof(var)) {
- vargood = 0;
- break;
+ if (argv[i][0] == '-') {
+ for (j = 1; argv[i][j] != 0; j++) {
+ int ch;
+
+ ch = argv[i][j];
+ switch (ch) {
+ case 'a':
+ howto |= RB_ASKNAME;
+ break;
+ case 'd':
+ howto |= RB_KDB;
+ break;
+ case 'D':
+ howto |= RB_MULTIPLE;
+ break;
+ case 'h':
+ howto |= RB_SERIAL;
+ break;
+ case 'm':
+ howto |= RB_MUTE;
+ break;
+ case 'p':
+ howto |= RB_PAUSE;
+ break;
+ case 'P':
+ if (!has_kbd)
+ howto |= RB_SERIAL | RB_MULTIPLE;
+ break;
+ case 'r':
+ howto |= RB_DFLTROOT;
+ break;
+ case 's':
+ howto |= RB_SINGLE;
+ break;
+ case 'S':
+ if (argv[i][j + 1] == 0) {
+ if (i + 1 == argc) {
+ setenv("comconsole_speed", "115200", 1);
+ } else {
+ cp16to8(&argv[i + 1][0], var,
+ sizeof(var));
+ setenv("comconsole_speedspeed", var, 1);
+ }
+ i++;
+ break;
+ } else {
+ cp16to8(&argv[i][j + 1], var,
+ sizeof(var));
+ setenv("comconsole_speed", var, 1);
+ break;
+ }
+ case 'v':
+ howto |= RB_VERBOSE;
+ break;
+ }
+ }
+ } else {
+ vargood = 0;
+ for (j = 0; argv[i][j] != 0; j++) {
+ if (j == sizeof(var)) {
+ vargood = 0;
+ break;
+ }
+ if (j > 0 && argv[i][j] == '=')
+ vargood = 1;
+ var[j] = (char)argv[i][j];
+ }
+ if (vargood) {
+ var[j] = 0;
+ putenv(var);
}
- if (j > 0 && argv[i][j] == '=')
- vargood = 1;
- var[j] = (char)argv[i][j];
- }
- if (vargood) {
- var[j] = 0;
- putenv(var);
}
}
+ for (i = 0; howto_names[i].ev != NULL; i++)
+ if (howto & howto_names[i].mask)
+ setenv(howto_names[i].ev, "YES", 1);
+ if (howto & RB_MULTIPLE) {
+ if (howto & RB_SERIAL)
+ setenv("console", "comconsole efi" , 1);
+ else
+ setenv("console", "efi comconsole" , 1);
+ } else if (howto & RB_SERIAL) {
+ setenv("console", "comconsole" , 1);
+ }
if (efi_copy_init()) {
printf("failed to allocate staging area\n");
@@ -198,6 +369,7 @@ main(int argc, CHAR16 *argv[])
efi_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
env_nounset);
+ init_zfs_bootenv(zfs_fmtdev(&currdev));
break;
}
#endif
@@ -504,6 +676,38 @@ command_lszfs(int argc, char *argv[])
}
return (CMD_OK);
}
+
+COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
+ command_reloadbe);
+
+static int
+command_reloadbe(int argc, char *argv[])
+{
+ int err;
+ char *root;
+
+ if (argc > 2) {
+ command_errmsg = "wrong number of arguments";
+ return (CMD_ERROR);
+ }
+
+ if (argc == 2) {
+ err = zfs_bootenv(argv[1]);
+ } else {
+ root = getenv("zfs_be_root");
+ if (root == NULL) {
+ return (CMD_OK);
+ }
+ err = zfs_bootenv(root);
+ }
+
+ if (err != 0) {
+ command_errmsg = strerror(err);
+ return (CMD_ERROR);
+ }
+
+ return (CMD_OK);
+}
#endif
#ifdef EFI_ZFS_BOOT
diff --git a/sys/boot/i386/boot2/boot2.c b/sys/boot/i386/boot2/boot2.c
index cd384e5..401a933 100644
--- a/sys/boot/i386/boot2/boot2.c
+++ b/sys/boot/i386/boot2/boot2.c
@@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$");
#include "boot2.h"
#include "lib.h"
+#include "paths.h"
+#include "rbx.h"
/* Define to 0 to omit serial support */
#ifndef SERIAL
@@ -52,46 +54,6 @@ __FBSDID("$FreeBSD$");
#define SECOND 18 /* Circa that many ticks in a second. */
-#define RBX_ASKNAME 0x0 /* -a */
-#define RBX_SINGLE 0x1 /* -s */
-/* 0x2 is reserved for log2(RB_NOSYNC). */
-/* 0x3 is reserved for log2(RB_HALT). */
-/* 0x4 is reserved for log2(RB_INITNAME). */
-#define RBX_DFLTROOT 0x5 /* -r */
-#define RBX_KDB 0x6 /* -d */
-/* 0x7 is reserved for log2(RB_RDONLY). */
-/* 0x8 is reserved for log2(RB_DUMP). */
-/* 0x9 is reserved for log2(RB_MINIROOT). */
-#define RBX_CONFIG 0xa /* -c */
-#define RBX_VERBOSE 0xb /* -v */
-#define RBX_SERIAL 0xc /* -h */
-#define RBX_CDROM 0xd /* -C */
-/* 0xe is reserved for log2(RB_POWEROFF). */
-#define RBX_GDB 0xf /* -g */
-#define RBX_MUTE 0x10 /* -m */
-/* 0x11 is reserved for log2(RB_SELFTEST). */
-/* 0x12 is reserved for boot programs. */
-/* 0x13 is reserved for boot programs. */
-#define RBX_PAUSE 0x14 /* -p */
-#define RBX_QUIET 0x15 /* -q */
-#define RBX_NOINTR 0x1c /* -n */
-/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
-#define RBX_DUAL 0x1d /* -D */
-/* 0x1f is reserved for log2(RB_BOOTINFO). */
-
-/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */
-#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \
- OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \
- OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \
- OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \
- OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \
- OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL))
-
-#define PATH_DOTCONFIG "/boot.config"
-#define PATH_CONFIG "/boot/config"
-#define PATH_BOOT3 "/boot/loader"
-#define PATH_KERNEL "/boot/kernel/kernel"
-
#define ARGS 0x900
#define NOPT 14
#define NDEV 3
@@ -106,9 +68,6 @@ __FBSDID("$FreeBSD$");
#define TYPE_MAXHARD TYPE_DA
#define TYPE_FD 2
-#define OPT_SET(opt) (1 << (opt))
-#define OPT_CHECK(opt) ((opts) & OPT_SET(opt))
-
extern uint32_t _end;
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
@@ -143,7 +102,7 @@ static struct dsk {
} dsk;
static char cmd[512], cmddup[512], knamebuf[1024];
static const char *kname;
-static uint32_t opts;
+uint32_t opts;
static struct bootinfo bootinfo;
#if SERIAL
static int comspeed = SIOSPD;
@@ -275,7 +234,7 @@ main(void)
*/
if (!kname) {
- kname = PATH_BOOT3;
+ kname = PATH_LOADER;
if (autoboot && !keyhit(3*SECOND)) {
load();
kname = PATH_KERNEL;
diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c
index 0596499..5316706 100644
--- a/sys/boot/i386/gptboot/gptboot.c
+++ b/sys/boot/i386/gptboot/gptboot.c
@@ -37,11 +37,7 @@ __FBSDID("$FreeBSD$");
#include "util.h"
#include "cons.h"
#include "gpt.h"
-
-#define PATH_DOTCONFIG "/boot.config"
-#define PATH_CONFIG "/boot/config"
-#define PATH_BOOT3 "/boot/loader"
-#define PATH_KERNEL "/boot/kernel/kernel"
+#include "paths.h"
#define ARGS 0x900
#define NOPT 14
@@ -180,7 +176,7 @@ main(void)
if (autoboot && keyhit(3)) {
if (*kname == '\0')
- memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
+ memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER));
break;
}
autoboot = 0;
@@ -192,7 +188,7 @@ main(void)
*/
if (*kname != '\0')
load();
- memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
+ memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER));
load();
memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
load();
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
index be08271..6e783cd 100644
--- a/sys/boot/i386/loader/main.c
+++ b/sys/boot/i386/loader/main.c
@@ -69,7 +69,6 @@ static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
#ifdef LOADER_ZFS_SUPPORT
-static void init_zfs_bootenv(char *currdev);
static void i386_zfs_probe(void);
#endif
@@ -303,34 +302,6 @@ extract_currdev(void)
env_nounset);
}
-#ifdef LOADER_ZFS_SUPPORT
-static void
-init_zfs_bootenv(char *currdev)
-{
- char *beroot;
-
- if (strlen(currdev) == 0)
- return;
- if(strncmp(currdev, "zfs:", 4) != 0)
- return;
- /* Remove the trailing : */
- currdev[strlen(currdev) - 1] = '\0';
- setenv("zfs_be_active", currdev, 1);
- setenv("zfs_be_currpage", "1", 1);
- /* Do not overwrite if already set */
- setenv("vfs.root.mountfrom", currdev, 0);
- /* Forward past zfs: */
- currdev = strchr(currdev, ':');
- currdev++;
- /* Remove the last element (current bootenv) */
- beroot = strrchr(currdev, '/');
- if (beroot != NULL)
- beroot[0] = '\0';
- beroot = currdev;
- setenv("zfs_be_root", beroot, 1);
-}
-#endif
-
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c
index ca82c63..6fbbc6f 100644
--- a/sys/boot/i386/zfsboot/zfsboot.c
+++ b/sys/boot/i386/zfsboot/zfsboot.c
@@ -42,14 +42,10 @@ __FBSDID("$FreeBSD$");
#include "util.h"
#include "cons.h"
#include "bootargs.h"
+#include "paths.h"
#include "libzfs.h"
-#define PATH_DOTCONFIG "/boot.config"
-#define PATH_CONFIG "/boot/config"
-#define PATH_BOOT3 "/boot/zfsloader"
-#define PATH_KERNEL "/boot/kernel/kernel"
-
#define ARGS 0x900
#define NOPT 14
#define NDEV 3
@@ -550,12 +546,12 @@ main(void)
}
/*
- * Try to exec stage 3 boot loader. If interrupted by a keypress,
+ * Try to exec /boot/loader. If interrupted by a keypress,
* or in case of failure, try to load a kernel directly instead.
*/
if (autoboot && !*kname) {
- memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
+ memcpy(kname, PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS));
if (!keyhit(3)) {
load();
memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
diff --git a/sys/boot/ia64/efi/main.c b/sys/boot/ia64/efi/main.c
index ec12b42..ca99c63a 100644
--- a/sys/boot/ia64/efi/main.c
+++ b/sys/boot/ia64/efi/main.c
@@ -179,7 +179,8 @@ main(int argc, CHAR16 *argv[])
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
bzero(&currdev, sizeof(currdev));
- efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
+ efi_handle_lookup(img->DeviceHandle, &currdev.d_dev,
+ &currdev.d_unit, NULL);
currdev.d_type = currdev.d_dev->dv_type;
env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset,
diff --git a/sys/boot/pc98/boot2/boot2.c b/sys/boot/pc98/boot2/boot2.c
index 72aae7d..bcd54f4 100644
--- a/sys/boot/pc98/boot2/boot2.c
+++ b/sys/boot/pc98/boot2/boot2.c
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
#include "boot2.h"
#include "lib.h"
+#include "paths.h"
+#include "rbx.h"
/* Define to 0 to omit serial support */
#ifndef SERIAL
@@ -54,46 +56,6 @@ __FBSDID("$FreeBSD$");
#define SECOND 1 /* Circa that many ticks in a second. */
-#define RBX_ASKNAME 0x0 /* -a */
-#define RBX_SINGLE 0x1 /* -s */
-/* 0x2 is reserved for log2(RB_NOSYNC). */
-/* 0x3 is reserved for log2(RB_HALT). */
-/* 0x4 is reserved for log2(RB_INITNAME). */
-#define RBX_DFLTROOT 0x5 /* -r */
-#define RBX_KDB 0x6 /* -d */
-/* 0x7 is reserved for log2(RB_RDONLY). */
-/* 0x8 is reserved for log2(RB_DUMP). */
-/* 0x9 is reserved for log2(RB_MINIROOT). */
-#define RBX_CONFIG 0xa /* -c */
-#define RBX_VERBOSE 0xb /* -v */
-#define RBX_SERIAL 0xc /* -h */
-#define RBX_CDROM 0xd /* -C */
-/* 0xe is reserved for log2(RB_POWEROFF). */
-#define RBX_GDB 0xf /* -g */
-#define RBX_MUTE 0x10 /* -m */
-/* 0x11 is reserved for log2(RB_SELFTEST). */
-/* 0x12 is reserved for boot programs. */
-/* 0x13 is reserved for boot programs. */
-#define RBX_PAUSE 0x14 /* -p */
-#define RBX_QUIET 0x15 /* -q */
-#define RBX_NOINTR 0x1c /* -n */
-/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
-#define RBX_DUAL 0x1d /* -D */
-/* 0x1f is reserved for log2(RB_BOOTINFO). */
-
-/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */
-#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \
- OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \
- OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \
- OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \
- OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \
- OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL))
-
-#define PATH_DOTCONFIG "/boot.config"
-#define PATH_CONFIG "/boot/config"
-#define PATH_BOOT3 "/boot/loader"
-#define PATH_KERNEL "/boot/kernel/kernel"
-
#define ARGS 0x900
#define NOPT 14
#define NDEV 3
@@ -105,9 +67,6 @@ __FBSDID("$FreeBSD$");
#define TYPE_DA 1
#define TYPE_FD 2
-#define OPT_SET(opt) (1 << (opt))
-#define OPT_CHECK(opt) ((opts) & OPT_SET(opt))
-
extern uint32_t _end;
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
@@ -145,7 +104,7 @@ static struct dsk {
} dsk;
static char cmd[512], cmddup[512], knamebuf[1024];
static const char *kname;
-static uint32_t opts;
+uint32_t opts;
static struct bootinfo bootinfo;
#if SERIAL
static int comspeed = SIOSPD;
@@ -414,7 +373,7 @@ main(void)
*/
if (!kname) {
- kname = PATH_BOOT3;
+ kname = PATH_LOADER;
if (autoboot && !keyhit(3*SECOND)) {
load();
kname = PATH_KERNEL;
diff --git a/sys/boot/powerpc/boot1.chrp/boot1.c b/sys/boot/powerpc/boot1.chrp/boot1.c
index af22488..9c50359 100644
--- a/sys/boot/powerpc/boot1.chrp/boot1.c
+++ b/sys/boot/powerpc/boot1.chrp/boot1.c
@@ -23,8 +23,7 @@ __FBSDID("$FreeBSD$");
#include <machine/elf.h>
#include <machine/stdarg.h>
-#define _PATH_LOADER "/boot/loader"
-#define _PATH_KERNEL "/boot/kernel/kernel"
+#include "paths.h"
#define BSIZEMAX 16384
@@ -396,7 +395,7 @@ main(int ac, char **av)
char bootpath_full[255];
int i, len;
- path = _PATH_LOADER;
+ path = PATH_LOADER;
for (i = 0; i < ac; i++) {
switch (av[i][0]) {
case '-':
diff --git a/sys/boot/sparc64/boot1/boot1.c b/sys/boot/sparc64/boot1/boot1.c
index 6c43c93..d0b7380 100644
--- a/sys/boot/sparc64/boot1/boot1.c
+++ b/sys/boot/sparc64/boot1/boot1.c
@@ -24,8 +24,8 @@ __FBSDID("$FreeBSD$");
#include <machine/elf.h>
#include <machine/stdarg.h>
-#define _PATH_LOADER "/boot/loader"
-#define _PATH_KERNEL "/boot/kernel/kernel"
+#include "paths.h"
+
#define READ_BUF_SIZE 8192
typedef int putc_func_t(char c, void *arg);
@@ -324,7 +324,7 @@ main(int ac, char **av)
const char *path;
int i;
- path = _PATH_LOADER;
+ path = PATH_LOADER;
for (i = 0; i < ac; i++) {
switch (av[i][0]) {
case '-':
diff --git a/sys/boot/userboot/userboot/main.c b/sys/boot/userboot/userboot/main.c
index e4d546a..d8e9349 100644
--- a/sys/boot/userboot/userboot/main.c
+++ b/sys/boot/userboot/userboot/main.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
static void userboot_zfs_probe(void);
static int userboot_zfs_found;
-static void init_zfs_bootenv(char *currdev);
#endif
#define USERBOOT_VERSION USERBOOT_VERSION_3
@@ -200,32 +199,6 @@ extract_currdev(void)
#if defined(USERBOOT_ZFS_SUPPORT)
static void
-init_zfs_bootenv(char *currdev)
-{
- char *beroot;
-
- if (strlen(currdev) == 0)
- return;
- if(strncmp(currdev, "zfs:", 4) != 0)
- return;
- /* Remove the trailing : */
- currdev[strlen(currdev) - 1] = '\0';
- setenv("zfs_be_active", currdev, 1);
- setenv("zfs_be_currpage", "1", 1);
- /* Do not overwrite if already set */
- setenv("vfs.root.mountfrom", currdev, 0);
- /* Forward past zfs: */
- currdev = strchr(currdev, ':');
- currdev++;
- /* Remove the last element (current bootenv) */
- beroot = strrchr(currdev, '/');
- if (beroot != NULL)
- beroot[0] = '\0';
- beroot = currdev;
- setenv("zfs_be_root", beroot, 1);
-}
-
-static void
userboot_zfs_probe(void)
{
char devname[32];
diff --git a/sys/boot/zfs/libzfs.h b/sys/boot/zfs/libzfs.h
index b289849..ee64d1c 100644
--- a/sys/boot/zfs/libzfs.h
+++ b/sys/boot/zfs/libzfs.h
@@ -62,6 +62,7 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
char *zfs_fmtdev(void *vdev);
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
+void init_zfs_bootenv(char *currdev);
int zfs_bootenv(const char *name);
int zfs_belist_add(const char *name);
int zfs_set_env(void);
diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c
index c339b2d..ef79cb4 100644
--- a/sys/boot/zfs/zfs.c
+++ b/sys/boot/zfs/zfs.c
@@ -709,6 +709,30 @@ zfs_list(const char *name)
return (zfs_list_dataset(spa, objid));
}
+void
+init_zfs_bootenv(char *currdev)
+{
+ char *beroot;
+
+ if (strlen(currdev) == 0)
+ return;
+ if(strncmp(currdev, "zfs:", 4) != 0)
+ return;
+ /* Remove the trailing : */
+ currdev[strlen(currdev) - 1] = '\0';
+ setenv("zfs_be_active", currdev, 1);
+ setenv("zfs_be_currpage", "1", 1);
+ /* Forward past zfs: */
+ currdev = strchr(currdev, ':');
+ currdev++;
+ /* Remove the last element (current bootenv) */
+ beroot = strrchr(currdev, '/');
+ if (beroot != NULL)
+ beroot[0] = '\0';
+ beroot = currdev;
+ setenv("zfs_be_root", beroot, 1);
+}
+
int
zfs_bootenv(const char *name)
{
@@ -779,8 +803,15 @@ int
zfs_belist_add(const char *name)
{
+ /* Skip special datasets that start with a $ character */
+ if (strncmp(name, "$", 1) == 0) {
+ return (0);
+ }
/* Add the boot environment to the head of the SLIST */
zfs_be = malloc(sizeof(struct zfs_be_entry));
+ if (zfs_be == NULL) {
+ return (ENOMEM);
+ }
zfs_be->name = name;
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries);
zfs_env_count++;
diff --git a/sys/conf/files b/sys/conf/files
index 3215795..8a71f9e 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1775,6 +1775,8 @@ dev/ixgbe/ix_txrx.c optional ix inet | ixv inet | ixgbe inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_phy.c optional ix inet | ixv inet | ixgbe inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_osdep.c optional ix inet | ixv inet | ixgbe inet \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_api.c optional ix inet | ixv inet | ixgbe inet \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_common.c optional ix inet | ixv inet | ixgbe inet \
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 09695ce..7a52fe7 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="10.3"
-BRANCH="BETA1"
+BRANCH="BETA2"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index e85c066..48ee76b 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -46,14 +46,10 @@
#endif
/*********************************************************************
- * Set this to one to display debug statistics
- *********************************************************************/
-int ixgbe_display_debug_stats = 0;
-
-/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "3.1.0";
+char ixgbe_driver_version[] = "3.1.13-k";
+
/*********************************************************************
* PCI Device ID Table
@@ -94,9 +90,11 @@ static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
/* required last entry */
{0, 0, 0, 0, 0}
};
@@ -130,7 +128,7 @@ static void ixgbe_media_status(struct ifnet *, struct ifmediareq *);
static int ixgbe_media_change(struct ifnet *);
static void ixgbe_identify_hardware(struct adapter *);
static int ixgbe_allocate_pci_resources(struct adapter *);
-static void ixgbe_get_slot_info(struct ixgbe_hw *);
+static void ixgbe_get_slot_info(struct adapter *);
static int ixgbe_allocate_msix(struct adapter *);
static int ixgbe_allocate_legacy(struct adapter *);
static int ixgbe_setup_msix(struct adapter *);
@@ -141,7 +139,6 @@ static void ixgbe_config_gpie(struct adapter *);
static void ixgbe_config_dmac(struct adapter *);
static void ixgbe_config_delay_values(struct adapter *);
static void ixgbe_config_link(struct adapter *);
-static void ixgbe_check_eee_support(struct adapter *);
static void ixgbe_check_wol_support(struct adapter *);
static int ixgbe_setup_low_power_mode(struct adapter *);
static void ixgbe_rearm_queues(struct adapter *, u64);
@@ -150,6 +147,7 @@ static void ixgbe_initialize_transmit_units(struct adapter *);
static void ixgbe_initialize_receive_units(struct adapter *);
static void ixgbe_enable_rx_drop(struct adapter *);
static void ixgbe_disable_rx_drop(struct adapter *);
+static void ixgbe_initialize_rss_mapping(struct adapter *);
static void ixgbe_enable_intr(struct adapter *);
static void ixgbe_disable_intr(struct adapter *);
@@ -167,22 +165,29 @@ static void ixgbe_unregister_vlan(void *, struct ifnet *, u16);
static void ixgbe_add_device_sysctls(struct adapter *);
static void ixgbe_add_hw_stats(struct adapter *);
+static int ixgbe_set_flowcntl(struct adapter *, int);
+static int ixgbe_set_advertise(struct adapter *, int);
/* Sysctl handlers */
static void ixgbe_set_sysctl_value(struct adapter *, const char *,
- const char *, int *, int);
-static int ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS);
-static int ixgbe_set_advertise(SYSCTL_HANDLER_ARGS);
+ const char *, int *, int);
+static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS);
+#ifdef IXGBE_DEBUG
+static int ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS);
+#endif
static int ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS);
static int ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS);
+static int ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS);
/* Support for pluggable optic modules */
static bool ixgbe_sfp_probe(struct adapter *);
@@ -290,6 +295,16 @@ SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN,
"Maximum number of sent packets to process at a time,"
"-1 means unlimited");
+/* Flow control setting, default to full */
+static int ixgbe_flow_control = ixgbe_fc_full;
+SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
+ &ixgbe_flow_control, 0, "Default flow control used for all adapters");
+
+/* Advertise Speed, default to 0 (auto) */
+static int ixgbe_advertise_speed = 0;
+SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN,
+ &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters");
+
/*
** Smart speed setting, default to on
** this only works as a compile option
@@ -317,7 +332,8 @@ SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0,
static int ixgbe_num_queues = 0;
TUNABLE_INT("hw.ix.num_queues", &ixgbe_num_queues);
SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0,
- "Number of queues to configure, 0 indicates autoconfigure");
+ "Number of queues to configure up to a mximum of 8,"
+ "0 indicates autoconfigure");
/*
** Number of TX descriptors per ring,
@@ -446,9 +462,13 @@ ixgbe_attach(device_t dev)
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
- adapter->dev = adapter->osdep.dev = dev;
+ adapter->dev = dev;
hw = &adapter->hw;
+#ifdef DEV_NETMAP
+ adapter->init_locked = ixgbe_init_locked;
+ adapter->stop_locked = ixgbe_stop;
+#endif
/* Core Lock Init*/
IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
@@ -531,18 +551,18 @@ ixgbe_attach(device_t dev)
adapter->sfp_probe = TRUE;
error = 0;
} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,"Unsupported SFP+ module detected!\n");
+ device_printf(dev, "Unsupported SFP+ module detected!\n");
error = EIO;
goto err_late;
} else if (error) {
- device_printf(dev,"Unable to initialize the shared code\n");
+ device_printf(dev, "Unable to initialize the shared code\n");
error = EIO;
goto err_late;
}
/* Make sure we have a good EEPROM before we read from it */
if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) {
- device_printf(dev,"The EEPROM Checksum Is Not Valid\n");
+ device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
error = EIO;
goto err_late;
}
@@ -552,23 +572,25 @@ ixgbe_attach(device_t dev)
case IXGBE_ERR_EEPROM_VERSION:
device_printf(dev, "This device is a pre-production adapter/"
"LOM. Please be aware there may be issues associated "
- "with your hardware.\n If you are experiencing problems "
+ "with your hardware.\nIf you are experiencing problems "
"please contact your Intel or hardware representative "
"who provided you with this hardware.\n");
break;
case IXGBE_ERR_SFP_NOT_SUPPORTED:
- device_printf(dev,"Unsupported SFP+ Module\n");
+ device_printf(dev, "Unsupported SFP+ Module\n");
error = EIO;
goto err_late;
case IXGBE_ERR_SFP_NOT_PRESENT:
- device_printf(dev,"No SFP+ Module found\n");
+ device_printf(dev, "No SFP+ Module found\n");
/* falls thru */
default:
break;
}
- /* Detect and set physical type */
- ixgbe_setup_optics(adapter);
+ /* hw.ix defaults init */
+ ixgbe_set_advertise(adapter, ixgbe_advertise_speed);
+ ixgbe_set_flowcntl(adapter, ixgbe_flow_control);
+ adapter->enable_aim = ixgbe_enable_aim;
if ((adapter->msix > 1) && (ixgbe_enable_msix))
error = ixgbe_allocate_msix(adapter);
@@ -577,6 +599,12 @@ ixgbe_attach(device_t dev)
if (error)
goto err_late;
+ /* Enable the optics for 82599 SFP+ fiber */
+ ixgbe_enable_tx_laser(hw);
+
+ /* Enable power to the phy. */
+ ixgbe_set_phy_power(hw, TRUE);
+
/* Setup OS specific network interface */
if (ixgbe_setup_interface(dev, adapter) != 0)
goto err_late;
@@ -591,11 +619,12 @@ ixgbe_attach(device_t dev)
ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
/* Check PCIE slot type/speed/width */
- ixgbe_get_slot_info(hw);
-
+ ixgbe_get_slot_info(adapter);
- /* Set an initial default flow control value */
+ /* Set an initial default flow control & dmac value */
adapter->fc = ixgbe_fc_full;
+ adapter->dmac = 0;
+ adapter->eee_enabled = 0;
#ifdef PCI_IOV
if ((hw->mac.type != ixgbe_mac_82598EB) && (adapter->msix > 1)) {
@@ -621,7 +650,6 @@ ixgbe_attach(device_t dev)
/* Check for certain supported features */
ixgbe_check_wol_support(adapter);
- ixgbe_check_eee_support(adapter);
/* Add sysctls */
ixgbe_add_device_sysctls(adapter);
@@ -682,6 +710,7 @@ ixgbe_detach(device_t dev)
}
#endif /* PCI_IOV */
+ ether_ifdetach(adapter->ifp);
/* Stop the adapter */
IXGBE_CORE_LOCK(adapter);
ixgbe_setup_low_power_mode(adapter);
@@ -721,7 +750,6 @@ ixgbe_detach(device_t dev)
if (adapter->vlan_detach != NULL)
EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
- ether_ifdetach(adapter->ifp);
callout_drain(&adapter->timer);
#ifdef DEV_NETMAP
netmap_detach(adapter->ifp);
@@ -776,10 +804,6 @@ ixgbe_suspend(device_t dev)
error = ixgbe_setup_low_power_mode(adapter);
- /* Save state and power down */
- pci_save_state(dev);
- pci_set_powerstate(dev, PCI_POWERSTATE_D3);
-
IXGBE_CORE_UNLOCK(adapter);
return (error);
@@ -797,9 +821,6 @@ ixgbe_resume(device_t dev)
IXGBE_CORE_LOCK(adapter);
- pci_set_powerstate(dev, PCI_POWERSTATE_D0);
- pci_restore_state(dev);
-
/* Read & clear WUS register */
wus = IXGBE_READ_REG(hw, IXGBE_WUS);
if (wus)
@@ -818,7 +839,6 @@ ixgbe_resume(device_t dev)
IXGBE_CORE_UNLOCK(adapter);
- INIT_DEBUGOUT("ixgbe_resume: end");
return (0);
}
@@ -862,7 +882,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
ixgbe_init(adapter);
-#if defined(INET)
+#ifdef INET
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
#endif
@@ -920,10 +940,21 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
break;
case SIOCSIFCAP:
{
- int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
- if (mask & IFCAP_HWCSUM)
- ifp->if_capenable ^= IFCAP_HWCSUM;
+
+ int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+ if (!mask)
+ break;
+
+ /* HW cannot turn these on/off separately */
+ if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+ ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
+ }
+ if (mask & IFCAP_TXCSUM)
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if (mask & IFCAP_TXCSUM_IPV6)
+ ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
if (mask & IFCAP_TSO4)
ifp->if_capenable ^= IFCAP_TSO4;
if (mask & IFCAP_TSO6)
@@ -936,6 +967,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
if (mask & IFCAP_VLAN_HWTSO)
ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
+
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
IXGBE_CORE_LOCK(adapter);
ixgbe_init_locked(adapter);
@@ -979,6 +1011,42 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
return (error);
}
+/*
+ * Set the various hardware offload abilities.
+ *
+ * This takes the ifnet's if_capenable flags (e.g. set by the user using
+ * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what
+ * mbuf offload flags the driver will understand.
+ */
+static void
+ixgbe_set_if_hwassist(struct adapter *adapter)
+{
+ struct ifnet *ifp = adapter->ifp;
+
+ ifp->if_hwassist = 0;
+#if __FreeBSD_version >= 1000000
+ if (ifp->if_capenable & IFCAP_TSO4)
+ ifp->if_hwassist |= CSUM_IP_TSO;
+ if (ifp->if_capenable & IFCAP_TSO6)
+ ifp->if_hwassist |= CSUM_IP6_TSO;
+ if (ifp->if_capenable & IFCAP_TXCSUM)
+ ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP |
+ CSUM_IP_SCTP);
+ if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
+ ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP |
+ CSUM_IP6_SCTP);
+#else
+ if (ifp->if_capenable & IFCAP_TSO)
+ ifp->if_hwassist |= CSUM_TSO;
+ if (ifp->if_capenable & IFCAP_TXCSUM) {
+ ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+ struct ixgbe_hw *hw = &adapter->hw;
+ if (hw->mac.type != ixgbe_mac_82598EB)
+ ifp->if_hwassist |= CSUM_SCTP;
+ }
+#endif
+}
+
/*********************************************************************
* Init entry point
*
@@ -1001,6 +1069,7 @@ ixgbe_init_locked(struct adapter *adapter)
struct rx_ring *rxr;
u32 txdctl, mhadd;
u32 rxdctl, rxctrl;
+ int err = 0;
#ifdef PCI_IOV
enum ixgbe_iov_mode mode;
#endif
@@ -1029,17 +1098,8 @@ ixgbe_init_locked(struct adapter *adapter)
ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
hw->addr_ctrl.rar_used_count = 1;
- /* Set the various hardware offload abilities */
- ifp->if_hwassist = 0;
- if (ifp->if_capenable & IFCAP_TSO)
- ifp->if_hwassist |= CSUM_TSO;
- if (ifp->if_capenable & IFCAP_TXCSUM) {
- ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
-#if __FreeBSD_version >= 800000
- if (hw->mac.type != ixgbe_mac_82598EB)
- ifp->if_hwassist |= CSUM_SCTP;
-#endif
- }
+ /* Set hardware offload abilities from ifnet flags */
+ ixgbe_set_if_hwassist(adapter);
/* Prepare transmit descriptors and buffers */
if (ixgbe_setup_transmit_structures(adapter)) {
@@ -1057,10 +1117,7 @@ ixgbe_init_locked(struct adapter *adapter)
/* Setup Multicast table */
ixgbe_set_multi(adapter);
- /*
- ** Determine the correct mbuf pool
- ** for doing jumbo frames
- */
+ /* Determine the correct mbuf pool, based on frame size */
if (adapter->max_frame_size <= MCLBYTES)
adapter->rx_mbuf_sz = MCLBYTES;
else
@@ -1196,7 +1253,7 @@ ixgbe_init_locked(struct adapter *adapter)
* need to be kick-started
*/
if (hw->phy.type == ixgbe_phy_none) {
- int err = hw->phy.ops.identify(hw);
+ err = hw->phy.ops.identify(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
device_printf(dev,
"Unsupported SFP+ module type was detected.\n");
@@ -1208,7 +1265,14 @@ ixgbe_init_locked(struct adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
/* Configure Energy Efficient Ethernet for supported devices */
- ixgbe_setup_eee(hw, adapter->eee_enabled);
+ if (hw->mac.ops.setup_eee) {
+ err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled);
+ if (err)
+ device_printf(dev, "Error setting up EEE: %d\n", err);
+ }
+
+ /* Enable power to the phy. */
+ ixgbe_set_phy_power(hw, TRUE);
/* Config/Enable Link */
ixgbe_config_link(adapter);
@@ -1278,7 +1342,7 @@ ixgbe_config_gpie(struct adapter *adapter)
/*
* Thermal Failure Detection (X540)
- * Link Detection (X557)
+ * Link Detection (X552 SFP+, X552/X557-AT)
*/
if (hw->mac.type == ixgbe_mac_X540 ||
hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
@@ -1511,7 +1575,7 @@ ixgbe_msix_que(void *arg)
/* Do AIM now? */
- if (ixgbe_enable_aim == FALSE)
+ if (adapter->enable_aim == FALSE)
goto no_calc;
/*
** Do Adaptive Interrupt Moderation:
@@ -1577,6 +1641,9 @@ ixgbe_msix_link(void *arg)
++adapter->link_irq;
+ /* Pause other interrupts */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
+
/* First get the cause */
reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
/* Be sure the queue bits are not cleared */
@@ -1585,8 +1652,10 @@ ixgbe_msix_link(void *arg)
IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
/* Link status change */
- if (reg_eicr & IXGBE_EICR_LSC)
+ if (reg_eicr & IXGBE_EICR_LSC) {
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ }
if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
#ifdef IXGBE_FDIR
@@ -1600,14 +1669,14 @@ ixgbe_msix_link(void *arg)
} else
#endif
if (reg_eicr & IXGBE_EICR_ECC) {
- device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
+ device_printf(adapter->dev, "CRITICAL: ECC ERROR!! "
"Please Reboot!!\n");
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
}
/* Check for over temp condition */
if (reg_eicr & IXGBE_EICR_TS) {
- device_printf(adapter->dev, "\nCRITICAL: OVER TEMP!! "
+ device_printf(adapter->dev, "CRITICAL: OVER TEMP!! "
"PHY IS SHUT DOWN!!\n");
device_printf(adapter->dev, "System shutdown required!\n");
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
@@ -1649,6 +1718,7 @@ ixgbe_msix_link(void *arg)
taskqueue_enqueue(adapter->tq, &adapter->phy_task);
}
+ /* Re-enable other interrupts */
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
return;
}
@@ -1742,6 +1812,7 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
** XXX: These need to use the proper media types once
** they're added.
*/
+#ifndef IFM_ETH_XTYPE
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
switch (adapter->link_speed) {
case IXGBE_LINK_SPEED_10GB_FULL:
@@ -1767,6 +1838,33 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
break;
}
+#else
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
+ break;
+ }
+ else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4
+ || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_2_5GB_FULL:
+ ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
+ break;
+ }
+#endif
/* If nothing is recognized... */
if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
@@ -1809,13 +1907,14 @@ ixgbe_media_change(struct ifnet * ifp)
return (EINVAL);
if (hw->phy.media_type == ixgbe_media_type_backplane)
- return (EPERM);
+ return (ENODEV);
/*
** We don't actually need to check against the supported
** media types of the adapter; ifmedia will take care of
** that for us.
*/
+#ifndef IFM_ETH_XTYPE
switch (IFM_SUBTYPE(ifm->ifm_media)) {
case IFM_AUTO:
case IFM_10G_T:
@@ -1841,6 +1940,33 @@ ixgbe_media_change(struct ifnet * ifp)
default:
goto invalid;
}
+#else
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ case IFM_10G_T:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ case IFM_10G_LRM:
+ case IFM_10G_KR:
+ case IFM_10G_LR:
+ case IFM_10G_KX4:
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ case IFM_10G_TWINAX:
+ speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ case IFM_1000_T:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ case IFM_1000_LX:
+ case IFM_1000_SX:
+ case IFM_1000_KX:
+ speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case IFM_100_TX:
+ speed |= IXGBE_LINK_SPEED_100_FULL;
+ break;
+ default:
+ goto invalid;
+ }
+#endif
hw->mac.autotry_restart = TRUE;
hw->mac.ops.setup_link(hw, speed, TRUE);
@@ -2377,7 +2503,7 @@ ixgbe_allocate_msix(struct adapter *adapter)
return (error);
}
#if __FreeBSD_version >= 800504
- bus_describe_intr(dev, que->res, que->tag, "que %d", i);
+ bus_describe_intr(dev, que->res, que->tag, "q%d", i);
#endif
que->msix = vector;
adapter->active_queues |= (u64)(1 << que->msix);
@@ -2426,8 +2552,8 @@ ixgbe_allocate_msix(struct adapter *adapter)
device_get_nameunit(adapter->dev),
cpu_id);
#else
- taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
- device_get_nameunit(adapter->dev));
+ taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d",
+ device_get_nameunit(adapter->dev), i);
#endif
}
@@ -2505,7 +2631,7 @@ ixgbe_setup_msix(struct adapter *adapter)
}
/* Figure out a reasonable auto config value */
- queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus;
+ queues = (mp_ncpus > (msgs - 1)) ? (msgs - 1) : mp_ncpus;
#ifdef RSS
/* If we're doing RSS, clamp at the number of RSS buckets */
@@ -2515,6 +2641,9 @@ ixgbe_setup_msix(struct adapter *adapter)
if (ixgbe_num_queues != 0)
queues = ixgbe_num_queues;
+ /* Set max queues to 8 when autoconfiguring */
+ else if ((ixgbe_num_queues == 0) && (queues > 8))
+ queues = 8;
/* reflect correct sysctl value */
ixgbe_num_queues = queues;
@@ -2551,12 +2680,12 @@ msi:
rid, adapter->msix_mem);
adapter->msix_mem = NULL;
}
- msgs = 1;
- if (pci_alloc_msi(dev, &msgs) == 0) {
- device_printf(adapter->dev,"Using an MSI interrupt\n");
+ msgs = 1;
+ if (pci_alloc_msi(dev, &msgs) == 0) {
+ device_printf(adapter->dev, "Using an MSI interrupt\n");
return (msgs);
}
- device_printf(adapter->dev,"Using a Legacy interrupt\n");
+ device_printf(adapter->dev, "Using a Legacy interrupt\n");
return (0);
}
@@ -2572,22 +2701,24 @@ ixgbe_allocate_pci_resources(struct adapter *adapter)
&rid, RF_ACTIVE);
if (!(adapter->pci_mem)) {
- device_printf(dev,"Unable to allocate bus resource: memory\n");
+ device_printf(dev, "Unable to allocate bus resource: memory\n");
return (ENXIO);
}
+ /* Save bus_space values for READ/WRITE_REG macros */
adapter->osdep.mem_bus_space_tag =
rman_get_bustag(adapter->pci_mem);
adapter->osdep.mem_bus_space_handle =
rman_get_bushandle(adapter->pci_mem);
+ /* Set hw values for shared code */
adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle;
+ adapter->hw.back = adapter;
- /* Legacy defaults */
+ /* Default to 1 queue if MSI-X setup fails */
adapter->num_queues = 1;
- adapter->hw.back = &adapter->osdep;
/*
- ** Now setup MSI or MSI/X, should
+ ** Now setup MSI or MSI-X, should
** return us the number of supported
** vectors. (Will be 1 for MSI)
*/
@@ -2712,13 +2843,22 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
*/
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
- ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO | IFCAP_VLAN_HWCSUM;
- ifp->if_capabilities |= IFCAP_JUMBO_MTU;
- ifp->if_capabilities |= IFCAP_LRO;
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
+ /* Set capability flags */
+ ifp->if_capabilities |= IFCAP_RXCSUM
+ | IFCAP_TXCSUM
+ | IFCAP_RXCSUM_IPV6
+ | IFCAP_TXCSUM_IPV6
+ | IFCAP_TSO4
+ | IFCAP_TSO6
+ | IFCAP_LRO
+ | IFCAP_VLAN_HWTAGGING
| IFCAP_VLAN_HWTSO
+ | IFCAP_VLAN_HWCSUM
+ | IFCAP_JUMBO_MTU
| IFCAP_VLAN_MTU
| IFCAP_HWSTATS;
+
+ /* Enable the above capabilities by default */
ifp->if_capenable = ifp->if_capabilities;
/*
@@ -2738,9 +2878,10 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
ixgbe_media_status);
+ adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
ixgbe_add_media_types(adapter);
- /* Autoselect media by default */
+ /* Set autoselect media by default */
ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
return (0);
@@ -2753,7 +2894,7 @@ ixgbe_add_media_types(struct adapter *adapter)
device_t dev = adapter->dev;
int layer;
- layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
+ layer = adapter->phy_layer;
/* Media types with matching FreeBSD media defines */
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
@@ -2767,20 +2908,28 @@ ixgbe_add_media_types(struct adapter *adapter)
layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR)
+ if (hw->phy.multispeed_fiber)
+ ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, NULL);
+ }
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+ if (hw->phy.multispeed_fiber)
+ ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
+ } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
+ ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
- /*
- ** Other (no matching FreeBSD media type):
- ** To workaround this, we'll assign these completely
- ** inappropriate media types.
- */
+#ifdef IFM_ETH_XTYPE
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+ ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
+ ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+ ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
+#else
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
device_printf(dev, "Media supported: 10GbaseKR\n");
device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
@@ -2796,10 +2945,9 @@ ixgbe_add_media_types(struct adapter *adapter)
device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
}
- if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) {
- /* Someday, someone will care about you... */
+#endif
+ if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
device_printf(dev, "Media supported: 1000baseBX\n");
- }
if (hw->device_id == IXGBE_DEV_ID_82598AT) {
ifmedia_add(&adapter->media,
@@ -2821,12 +2969,7 @@ ixgbe_config_link(struct adapter *adapter)
sfp = ixgbe_is_sfp(hw);
if (sfp) {
- if (hw->phy.multispeed_fiber) {
- hw->mac.ops.setup_sfp(hw);
- ixgbe_enable_tx_laser(hw);
- taskqueue_enqueue(adapter->tq, &adapter->msf_task);
- } else
- taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+ taskqueue_enqueue(adapter->tq, &adapter->mod_task);
} else {
if (hw->mac.ops.check_link)
err = ixgbe_check_link(hw, &adapter->link_speed,
@@ -2860,7 +3003,6 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
/* Setup the Base and Length of the Tx Descriptor Ring */
-
for (int i = 0; i < adapter->num_queues; i++, txr++) {
u64 tdba = txr->txdma.dma_paddr;
u32 txctrl = 0;
@@ -2880,12 +3022,15 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
txr->tail = IXGBE_TDT(j);
/* Disable Head Writeback */
+ /*
+ * Note: for X550 series devices, these registers are actually
+ * prefixed with TPH_ isntead of DCA_, but the addresses and
+ * fields remain the same.
+ */
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
default:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
break;
@@ -2895,8 +3040,6 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
case ixgbe_mac_82598EB:
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
default:
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
break;
@@ -2929,7 +3072,7 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
}
static void
-ixgbe_initialise_rss_mapping(struct adapter *adapter)
+ixgbe_initialize_rss_mapping(struct adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 reta = 0, mrqc, rss_key[10];
@@ -3064,7 +3207,6 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
u32 bufsz, fctrl, srrctl, rxcsum;
u32 hlreg;
-
/*
* Make sure receives are disabled while
* setting up the descriptor ring
@@ -3129,11 +3271,11 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
srrctl &= ~IXGBE_SRRCTL_DROP_EN;
}
- IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
+ IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
/* Setup the HW Rx Head and Tail Descriptor Pointers */
- IXGBE_WRITE_REG(hw, IXGBE_RDH(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RDT(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
/* Set the driver rx tail address */
rxr->tail = IXGBE_RDT(rxr->me);
@@ -3149,7 +3291,7 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
- ixgbe_initialise_rss_mapping(adapter);
+ ixgbe_initialize_rss_mapping(adapter);
if (adapter->num_queues > 1) {
/* RSS and RX IPP Checksum are mutually exclusive */
@@ -3159,6 +3301,7 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
if (ifp->if_capenable & IFCAP_RXCSUM)
rxcsum |= IXGBE_RXCSUM_PCSD;
+ /* This is useful for calculating UDP/IP fragment checksums */
if (!(rxcsum & IXGBE_RXCSUM_PCSD))
rxcsum |= IXGBE_RXCSUM_IPPCSE;
@@ -3380,9 +3523,10 @@ ixgbe_disable_intr(struct adapter *adapter)
** the slot this adapter is plugged into.
*/
static void
-ixgbe_get_slot_info(struct ixgbe_hw *hw)
+ixgbe_get_slot_info(struct adapter *adapter)
{
- device_t dev = ((struct ixgbe_osdep *)hw->back)->dev;
+ device_t dev = adapter->dev;
+ struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_mac_info *mac = &hw->mac;
u16 link;
u32 offset;
@@ -3589,12 +3733,12 @@ ixgbe_sfp_probe(struct adapter *adapter)
goto out;
ret = hw->phy.ops.reset(hw);
if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,"Unsupported SFP+ module detected!");
- printf(" Reload driver with supported module.\n");
+ device_printf(dev, "Unsupported SFP+ module detected!");
+ device_printf(dev, "Reload driver with supported module.\n");
adapter->sfp_probe = FALSE;
goto out;
} else
- device_printf(dev,"SFP+ module detected!\n");
+ device_printf(dev, "SFP+ module detected!\n");
/* We now have supported optics */
adapter->sfp_probe = FALSE;
/* Set the optics type so system reports correctly */
@@ -3613,10 +3757,14 @@ static void
ixgbe_handle_link(void *context, int pending)
{
struct adapter *adapter = context;
+ struct ixgbe_hw *hw = &adapter->hw;
- ixgbe_check_link(&adapter->hw,
+ ixgbe_check_link(hw,
&adapter->link_speed, &adapter->link_up, 0);
ixgbe_update_link_status(adapter);
+
+ /* Re-enable link interrupts */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
}
/*
@@ -3627,23 +3775,66 @@ ixgbe_handle_mod(void *context, int pending)
{
struct adapter *adapter = context;
struct ixgbe_hw *hw = &adapter->hw;
+ enum ixgbe_phy_type orig_type = hw->phy.type;
device_t dev = adapter->dev;
u32 err;
+ IXGBE_CORE_LOCK(adapter);
+
+ /* Check to see if the PHY type changed */
+ if (hw->phy.ops.identify) {
+ hw->phy.type = ixgbe_phy_unknown;
+ hw->phy.ops.identify(hw);
+ }
+
+ if (hw->phy.type != orig_type) {
+ device_printf(dev, "Detected phy_type %d\n", hw->phy.type);
+
+ if (hw->phy.type == ixgbe_phy_none) {
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ goto out;
+ }
+
+ /* Try to do the initialization that was skipped before */
+ if (hw->phy.ops.init)
+ hw->phy.ops.init(hw);
+ if (hw->phy.ops.reset)
+ hw->phy.ops.reset(hw);
+ }
+
err = hw->phy.ops.identify_sfp(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
device_printf(dev,
"Unsupported SFP+ module type was detected.\n");
- return;
+ goto out;
}
err = hw->mac.ops.setup_sfp(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
device_printf(dev,
"Setup failure - unsupported SFP+ module type.\n");
- return;
+ goto out;
+ }
+ if (hw->phy.multispeed_fiber)
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+out:
+ /* Update media type */
+ switch (hw->mac.ops.get_media_type(hw)) {
+ case ixgbe_media_type_fiber:
+ adapter->optics = IFM_10G_SR;
+ break;
+ case ixgbe_media_type_copper:
+ adapter->optics = IFM_10G_TWINAX;
+ break;
+ case ixgbe_media_type_cx4:
+ adapter->optics = IFM_10G_CX4;
+ break;
+ default:
+ adapter->optics = 0;
+ break;
}
- taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+
+ IXGBE_CORE_UNLOCK(adapter);
return;
}
@@ -3658,13 +3849,10 @@ ixgbe_handle_msf(void *context, int pending)
struct ixgbe_hw *hw = &adapter->hw;
u32 autoneg;
bool negotiate;
- int err;
- err = hw->phy.ops.identify_sfp(hw);
- if (!err) {
- ixgbe_setup_optics(adapter);
- INIT_DEBUGOUT1("ixgbe_sfp_probe: flags: %X\n", adapter->optics);
- }
+ IXGBE_CORE_LOCK(adapter);
+ /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
+ adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
autoneg = hw->phy.autoneg_advertised;
if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
@@ -3672,8 +3860,10 @@ ixgbe_handle_msf(void *context, int pending)
if (hw->mac.ops.setup_link)
hw->mac.ops.setup_link(hw, autoneg, TRUE);
+ /* Adjust media types shown in ifconfig */
ifmedia_removeall(&adapter->media);
ixgbe_add_media_types(adapter);
+ IXGBE_CORE_UNLOCK(adapter);
return;
}
@@ -3751,18 +3941,6 @@ ixgbe_config_dmac(struct adapter *adapter)
}
/*
- * Checks whether the adapter supports Energy Efficient Ethernet
- * or not, based on device ID.
- */
-static void
-ixgbe_check_eee_support(struct adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
-
- adapter->eee_enabled = !!(hw->mac.ops.setup_eee);
-}
-
-/*
* Checks whether the adapter's ports are capable of
* Wake On LAN by reading the adapter's NVM.
*
@@ -3780,8 +3958,8 @@ ixgbe_check_wol_support(struct adapter *adapter)
ixgbe_get_device_caps(hw, &dev_caps);
if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
- hw->bus.func == 0))
- adapter->wol_support = hw->wol_enabled = 1;
+ hw->bus.func == 0))
+ adapter->wol_support = hw->wol_enabled = 1;
/* Save initial wake up filter configuration */
adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
@@ -3801,6 +3979,9 @@ ixgbe_setup_low_power_mode(struct adapter *adapter)
mtx_assert(&adapter->core_mtx, MA_OWNED);
+ if (!hw->wol_enabled)
+ ixgbe_set_phy_power(hw, FALSE);
+
/* Limit power management flow to X550EM baseT */
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T
&& hw->phy.ops.enter_lplu) {
@@ -4114,7 +4295,7 @@ ixgbe_add_device_sysctls(struct adapter *adapter)
/* Sysctls for all devices */
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc",
CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_set_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC);
+ ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC);
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim",
CTLFLAG_RW,
@@ -4122,20 +4303,30 @@ ixgbe_add_device_sysctls(struct adapter *adapter)
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed",
CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
- ixgbe_set_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED);
+ ixgbe_sysctl_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED);
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "thermal_test",
CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
ixgbe_sysctl_thermal_test, "I", "Thermal Test");
- /* for X550 devices */
+#ifdef IXGBE_DEBUG
+ /* testing sysctls (for all devices) */
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state",
+ CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
+ ixgbe_sysctl_power_state, "I", "PCI Power State");
+
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
+ CTLTYPE_STRING | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration");
+#endif
+ /* for X550 series devices */
if (hw->mac.type >= ixgbe_mac_X550)
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac",
CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
ixgbe_sysctl_dmac, "I", "DMA Coalesce");
- /* for X550T and X550EM backplane devices */
- if (hw->mac.ops.setup_eee) {
+ /* for X552 backplane devices */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
struct sysctl_oid *eee_node;
struct sysctl_oid_list *eee_list;
@@ -4163,11 +4354,15 @@ ixgbe_add_device_sysctls(struct adapter *adapter)
CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
ixgbe_sysctl_eee_rx_lpi_status, "I",
"Whether or not RX link is in LPI state");
+
+ SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_delay",
+ CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
+ ixgbe_sysctl_eee_tx_lpi_delay, "I",
+ "TX LPI entry delay in microseconds");
}
- /* for certain 10GBaseT devices */
- if (hw->device_id == IXGBE_DEV_ID_X550T ||
- hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+ /* for WoL-capable devices */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable",
CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
ixgbe_sysctl_wol_enable, "I",
@@ -4179,7 +4374,7 @@ ixgbe_add_device_sysctls(struct adapter *adapter)
"Enable/Disable Wake Up Filters");
}
- /* for X550EM 10GBaseT devices */
+ /* for X552/X557-AT devices */
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
struct sysctl_oid *phy_node;
struct sysctl_oid_list *phy_list;
@@ -4473,41 +4668,51 @@ ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
** 3 - full
*/
static int
-ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS)
+ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS)
{
- int error, last;
- struct adapter *adapter = (struct adapter *) arg1;
+ int error, fc;
+ struct adapter *adapter;
- last = adapter->fc;
- error = sysctl_handle_int(oidp, &adapter->fc, 0, req);
+ adapter = (struct adapter *) arg1;
+ fc = adapter->fc;
+
+ error = sysctl_handle_int(oidp, &fc, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
/* Don't bother if it's not changed */
- if (adapter->fc == last)
+ if (adapter->fc == fc)
return (0);
- switch (adapter->fc) {
- case ixgbe_fc_rx_pause:
- case ixgbe_fc_tx_pause:
- case ixgbe_fc_full:
- adapter->hw.fc.requested_mode = adapter->fc;
- if (adapter->num_queues > 1)
- ixgbe_disable_rx_drop(adapter);
- break;
- case ixgbe_fc_none:
- adapter->hw.fc.requested_mode = ixgbe_fc_none;
- if (adapter->num_queues > 1)
- ixgbe_enable_rx_drop(adapter);
- break;
- default:
- adapter->fc = last;
- return (EINVAL);
+ return ixgbe_set_flowcntl(adapter, fc);
+}
+
+
+static int
+ixgbe_set_flowcntl(struct adapter *adapter, int fc)
+{
+
+ switch (fc) {
+ case ixgbe_fc_rx_pause:
+ case ixgbe_fc_tx_pause:
+ case ixgbe_fc_full:
+ adapter->hw.fc.requested_mode = adapter->fc;
+ if (adapter->num_queues > 1)
+ ixgbe_disable_rx_drop(adapter);
+ break;
+ case ixgbe_fc_none:
+ adapter->hw.fc.requested_mode = ixgbe_fc_none;
+ if (adapter->num_queues > 1)
+ ixgbe_enable_rx_drop(adapter);
+ break;
+ default:
+ return (EINVAL);
}
+ adapter->fc = fc;
/* Don't autoneg if forcing a value */
adapter->hw.fc.disable_fc_autoneg = TRUE;
ixgbe_fc_enable(&adapter->hw);
- return error;
+ return (0);
}
/*
@@ -4518,27 +4723,39 @@ ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS)
** 0x4 - advertise 10G
*/
static int
-ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
+ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
{
- int error = 0, requested;
- struct adapter *adapter;
- device_t dev;
- struct ixgbe_hw *hw;
- ixgbe_link_speed speed = 0;
+ int error, advertise;
+ struct adapter *adapter;
adapter = (struct adapter *) arg1;
- dev = adapter->dev;
- hw = &adapter->hw;
+ advertise = adapter->advertise;
- requested = adapter->advertise;
- error = sysctl_handle_int(oidp, &requested, 0, req);
+ error = sysctl_handle_int(oidp, &advertise, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
/* Checks to validate new value */
- if (adapter->advertise == requested) /* no change */
+ if (adapter->advertise == advertise) /* no change */
return (0);
+ return ixgbe_set_advertise(adapter, advertise);
+}
+
+static int
+ixgbe_set_advertise(struct adapter *adapter, int advertise)
+{
+ device_t dev;
+ struct ixgbe_hw *hw;
+ ixgbe_link_speed speed;
+
+ hw = &adapter->hw;
+ dev = adapter->dev;
+
+ /* No speed changes for backplane media */
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ return (ENODEV);
+
if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
(hw->phy.multispeed_fiber))) {
device_printf(dev,
@@ -4547,13 +4764,13 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
return (EINVAL);
}
- if (requested < 0x1 || requested > 0x7) {
+ if (advertise < 0x1 || advertise > 0x7) {
device_printf(dev,
"Invalid advertised speed; valid modes are 0x1 through 0x7\n");
return (EINVAL);
}
- if ((requested & 0x1)
+ if ((advertise & 0x1)
&& (hw->mac.type != ixgbe_mac_X540)
&& (hw->mac.type != ixgbe_mac_X550)) {
device_printf(dev, "Set Advertise: 100Mb on X540/X550 only\n");
@@ -4561,22 +4778,23 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
}
/* Set new value and report new advertised mode */
- if (requested & 0x1)
+ speed = 0;
+ if (advertise & 0x1)
speed |= IXGBE_LINK_SPEED_100_FULL;
- if (requested & 0x2)
+ if (advertise & 0x2)
speed |= IXGBE_LINK_SPEED_1GB_FULL;
- if (requested & 0x4)
+ if (advertise & 0x4)
speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ adapter->advertise = advertise;
hw->mac.autotry_restart = TRUE;
hw->mac.ops.setup_link(hw, speed, TRUE);
- adapter->advertise = requested;
- return (error);
+ return (0);
}
/*
- * The following two sysctls are for X550 BaseT devices;
+ * The following two sysctls are for X552/X557-AT devices;
* they deal with the external PHY used in them.
*/
static int
@@ -4675,31 +4893,22 @@ static int
ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
{
struct adapter *adapter = (struct adapter *) arg1;
- struct ixgbe_hw *hw = &adapter->hw;
struct ifnet *ifp = adapter->ifp;
int error;
- u16 oldval;
+ u32 newval;
- oldval = adapter->dmac;
- error = sysctl_handle_int(oidp, &adapter->dmac, 0, req);
+ newval = adapter->dmac;
+ error = sysctl_handle_int(oidp, &newval, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
- switch (hw->mac.type) {
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- break;
- default:
- device_printf(adapter->dev,
- "DMA Coalescing is only supported on X550 devices\n");
- return (ENODEV);
- }
-
- switch (adapter->dmac) {
+ switch (newval) {
case 0:
/* Disabled */
+ adapter->dmac = 0;
break;
- case 1: /* Enable and use default */
+ case 1:
+ /* Enable and use default */
adapter->dmac = 1000;
break;
case 50:
@@ -4711,10 +4920,10 @@ ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
case 5000:
case 10000:
/* Legal values - allow */
+ adapter->dmac = newval;
break;
default:
/* Do nothing, illegal value */
- adapter->dmac = oldval;
return (EINVAL);
}
@@ -4725,6 +4934,42 @@ ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
return (0);
}
+#ifdef IXGBE_DEBUG
+/**
+ * Sysctl to test power states
+ * Values:
+ * 0 - set device to D0
+ * 3 - set device to D3
+ * (none) - get current device power state
+ */
+static int
+ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ device_t dev = adapter->dev;
+ int curr_ps, new_ps, error = 0;
+
+ curr_ps = new_ps = pci_get_powerstate(dev);
+
+ error = sysctl_handle_int(oidp, &new_ps, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (new_ps == curr_ps)
+ return (0);
+
+ if (new_ps == 3 && curr_ps == 0)
+ error = DEVICE_SUSPEND(dev);
+ else if (new_ps == 0 && curr_ps == 3)
+ error = DEVICE_RESUME(dev);
+ else
+ return (EINVAL);
+
+ device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
+
+ return (error);
+}
+#endif
/*
* Sysctl to enable/disable the WoL capability, if supported by the adapter.
* Values:
@@ -4743,13 +4988,14 @@ ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
+ new_wol_enabled = !!(new_wol_enabled);
if (new_wol_enabled == hw->wol_enabled)
return (0);
if (new_wol_enabled > 0 && !adapter->wol_support)
return (ENODEV);
else
- hw->wol_enabled = !!(new_wol_enabled);
+ hw->wol_enabled = new_wol_enabled;
return (0);
}
@@ -4773,13 +5019,14 @@ ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_int(oidp, &new_eee_enabled, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
+ new_eee_enabled = !!(new_eee_enabled);
if (new_eee_enabled == adapter->eee_enabled)
return (0);
if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee)
return (ENODEV);
else
- adapter->eee_enabled = !!(new_eee_enabled);
+ adapter->eee_enabled = new_eee_enabled;
/* Re-initialize hardware if it's already running */
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -4837,6 +5084,21 @@ ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS)
}
/*
+ * Read-only sysctl indicating TX Link LPI delay
+ */
+static int
+ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reg;
+
+ reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU);
+
+ return (sysctl_handle_int(oidp, 0, reg >> 26, req));
+}
+
+/*
* Sysctl to enable/disable the types of packets that the
* adapter will wake up on upon receipt.
* WUFC - Wake Up Filter Control
@@ -4879,6 +5141,58 @@ ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS)
return (0);
}
+#ifdef IXGBE_DEBUG
+static int
+ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *)arg1;
+ struct ixgbe_hw *hw = &adapter->hw;
+ device_t dev = adapter->dev;
+ int error = 0, reta_size;
+ struct sbuf *buf;
+ u32 reg;
+
+ buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+ if (!buf) {
+ device_printf(dev, "Could not allocate sbuf for output.\n");
+ return (ENOMEM);
+ }
+
+ // TODO: use sbufs to make a string to print out
+ /* Set multiplier for RETA setup and table size based on MAC */
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X550:
+ case ixgbe_mac_X550EM_x:
+ reta_size = 128;
+ break;
+ default:
+ reta_size = 32;
+ break;
+ }
+
+ /* Print out the redirection table */
+ sbuf_cat(buf, "\n");
+ for (int i = 0; i < reta_size; i++) {
+ if (i < 32) {
+ reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
+ sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
+ } else {
+ reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
+ sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
+ }
+ }
+
+ // TODO: print more config
+
+ error = sbuf_finish(buf);
+ if (error)
+ device_printf(dev, "Error finishing sbuf: %d\n", error);
+
+ sbuf_delete(buf);
+ return (0);
+}
+#endif /* IXGBE_DEBUG */
+
/*
** Enable the hardware to drop packets when the buffer is
** full. This is useful when multiqueue,so that no single
diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c
index a3971cc..f47cf60 100644
--- a/sys/dev/ixgbe/if_ixv.c
+++ b/sys/dev/ixgbe/if_ixv.c
@@ -43,7 +43,7 @@
/*********************************************************************
* Driver version
*********************************************************************/
-char ixv_driver_version[] = "1.4.0";
+char ixv_driver_version[] = "1.4.6-k";
/*********************************************************************
* PCI Device ID Table
@@ -292,9 +292,14 @@ ixv_attach(device_t dev)
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
- adapter->dev = adapter->osdep.dev = dev;
+ adapter->dev = dev;
hw = &adapter->hw;
+#ifdef DEV_NETMAP
+ adapter->init_locked = ixv_init_locked;
+ adapter->stop_locked = ixv_stop;
+#endif
+
/* Core Lock Init*/
IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
@@ -317,7 +322,7 @@ ixv_attach(device_t dev)
/* Do base PCI setup - map BAR0 */
if (ixv_allocate_pci_resources(adapter)) {
- device_printf(dev, "Allocation of PCI resources failed\n");
+ device_printf(dev, "ixv_allocate_pci_resources() failed!\n");
error = ENXIO;
goto err_out;
}
@@ -357,6 +362,7 @@ ixv_attach(device_t dev)
/* Allocate our TX/RX Queues */
if (ixgbe_allocate_queues(adapter)) {
+ device_printf(dev, "ixgbe_allocate_queues() failed!\n");
error = ENOMEM;
goto err_out;
}
@@ -367,7 +373,7 @@ ixv_attach(device_t dev)
*/
error = ixgbe_init_shared_code(hw);
if (error) {
- device_printf(dev,"Shared Code Initialization Failure\n");
+ device_printf(dev, "ixgbe_init_shared_code() failed!\n");
error = EIO;
goto err_late;
}
@@ -375,23 +381,37 @@ ixv_attach(device_t dev)
/* Setup the mailbox */
ixgbe_init_mbx_params_vf(hw);
- ixgbe_reset_hw(hw);
+ /* Reset mbox api to 1.0 */
+ error = ixgbe_reset_hw(hw);
+ if (error == IXGBE_ERR_RESET_FAILED)
+ device_printf(dev, "ixgbe_reset_hw() failure: Reset Failed!\n");
+ else if (error)
+ device_printf(dev, "ixgbe_reset_hw() failed with error %d\n", error);
+ if (error) {
+ error = EIO;
+ goto err_late;
+ }
- /* Get the Mailbox API version */
- device_printf(dev,"MBX API %d negotiation: %d\n",
- ixgbe_mbox_api_11,
- ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11));
+ /* Negotiate mailbox API version */
+ error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
+ if (error) {
+ device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
+ error = EIO;
+ goto err_late;
+ }
error = ixgbe_init_hw(hw);
if (error) {
- device_printf(dev,"Hardware Initialization Failure\n");
+ device_printf(dev, "ixgbe_init_hw() failed!\n");
error = EIO;
goto err_late;
}
error = ixv_allocate_msix(adapter);
- if (error)
+ if (error) {
+ device_printf(dev, "ixv_allocate_msix() failed!\n");
goto err_late;
+ }
/* If no mac address was assigned, make a random one */
if (!ixv_check_ether_addr(hw->mac.addr)) {
@@ -451,7 +471,7 @@ ixv_detach(device_t dev)
/* Make sure VLANS are not using driver */
if (adapter->ifp->if_vlantrunk != NULL) {
- device_printf(dev,"Vlan in use, detach first\n");
+ device_printf(dev, "Vlan in use, detach first\n");
return (EBUSY);
}
@@ -560,13 +580,13 @@ ixv_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
#endif
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
- if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
+ if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) {
error = EINVAL;
} else {
IXGBE_CORE_LOCK(adapter);
ifp->if_mtu = ifr->ifr_mtu;
adapter->max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ ifp->if_mtu + IXGBE_MTU_HDR;
ixv_init_locked(adapter);
IXGBE_CORE_UNLOCK(adapter);
}
@@ -647,9 +667,9 @@ ixv_init_locked(struct adapter *adapter)
struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
struct ixgbe_hw *hw = &adapter->hw;
- u32 mhadd, gpie;
+ int error = 0;
- INIT_DEBUGOUT("ixv_init: begin");
+ INIT_DEBUGOUT("ixv_init_locked: begin");
mtx_assert(&adapter->core_mtx, MA_OWNED);
hw->adapter_stopped = FALSE;
ixgbe_stop_adapter(hw);
@@ -666,12 +686,17 @@ ixv_init_locked(struct adapter *adapter)
/* Prepare transmit descriptors and buffers */
if (ixgbe_setup_transmit_structures(adapter)) {
- device_printf(dev,"Could not setup transmit structures\n");
+ device_printf(dev, "Could not setup transmit structures\n");
ixv_stop(adapter);
return;
}
+ /* Reset VF and renegotiate mailbox API version */
ixgbe_reset_hw(hw);
+ error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
+ if (error)
+ device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
+
ixv_initialize_transmit_units(adapter);
/* Setup Multicast table */
@@ -688,7 +713,7 @@ ixv_init_locked(struct adapter *adapter)
/* Prepare receive descriptors and buffers */
if (ixgbe_setup_receive_structures(adapter)) {
- device_printf(dev,"Could not setup receive structures\n");
+ device_printf(dev, "Could not setup receive structures\n");
ixv_stop(adapter);
return;
}
@@ -696,12 +721,6 @@ ixv_init_locked(struct adapter *adapter)
/* Configure RX settings */
ixv_initialize_receive_units(adapter);
- /* Enable Enhanced MSIX mode */
- gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
- gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME;
- gpie |= IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD;
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-
/* Set the various hardware offload abilities */
ifp->if_hwassist = 0;
if (ifp->if_capenable & IFCAP_TSO4)
@@ -713,19 +732,9 @@ ixv_init_locked(struct adapter *adapter)
#endif
}
- /* Set MTU size */
- if (ifp->if_mtu > ETHERMTU) {
- mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
- mhadd &= ~IXGBE_MHADD_MFS_MASK;
- mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
- IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
- }
-
/* Set up VLAN offload and filter */
ixv_setup_vlan_support(adapter);
- callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
-
/* Set up MSI/X routing */
ixv_configure_ivars(adapter);
@@ -741,6 +750,9 @@ ixv_init_locked(struct adapter *adapter)
/* Config/Enable Link */
ixv_config_link(adapter);
+ /* Start watchdog */
+ callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
+
/* And now turn on interrupts */
ixv_enable_intr(adapter);
@@ -1415,7 +1427,7 @@ ixv_allocate_pci_resources(struct adapter *adapter)
&rid, RF_ACTIVE);
if (!(adapter->pci_mem)) {
- device_printf(dev,"Unable to allocate bus resource: memory\n");
+ device_printf(dev, "Unable to allocate bus resource: memory\n");
return (ENXIO);
}
@@ -1423,12 +1435,11 @@ ixv_allocate_pci_resources(struct adapter *adapter)
rman_get_bustag(adapter->pci_mem);
adapter->osdep.mem_bus_space_handle =
rman_get_bushandle(adapter->pci_mem);
- adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle;
+ adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
/* Pick up the tuneable queues */
adapter->num_queues = ixv_num_queues;
-
- adapter->hw.back = &adapter->osdep;
+ adapter->hw.back = adapter;
/*
** Now setup MSI/X, should
@@ -1536,7 +1547,7 @@ ixv_setup_interface(device_t dev, struct adapter *adapter)
ether_ifattach(ifp, adapter->hw.mac.addr);
adapter->max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ ifp->if_mtu + IXGBE_MTU_HDR_VLAN;
/*
* Tell the upper layer(s) we support long frames.
@@ -1557,7 +1568,6 @@ ixv_setup_interface(device_t dev, struct adapter *adapter)
*/
ifmedia_init(&adapter->media, IFM_IMASK, ixv_media_change,
ixv_media_status);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_FDX, 0, NULL);
ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
@@ -1568,19 +1578,11 @@ static void
ixv_config_link(struct adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 autoneg, err = 0;
+ u32 autoneg;
if (hw->mac.ops.check_link)
- err = hw->mac.ops.check_link(hw, &autoneg,
+ hw->mac.ops.check_link(hw, &autoneg,
&adapter->link_up, FALSE);
- if (err)
- goto out;
-
- if (hw->mac.ops.setup_link)
- err = hw->mac.ops.setup_link(hw,
- autoneg, adapter->link_up);
-out:
- return;
}
@@ -1647,7 +1649,6 @@ ixv_initialize_receive_units(struct adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
struct ifnet *ifp = adapter->ifp;
u32 bufsz, rxcsum, psrtype;
- int max_frame;
if (ifp->if_mtu > ETHERMTU)
bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
@@ -1660,9 +1661,8 @@ ixv_initialize_receive_units(struct adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype);
- /* Tell PF our expected packet-size */
- max_frame = ifp->if_mtu + IXGBE_MTU_HDR;
- ixgbevf_rlpml_set_vf(hw, max_frame);
+ /* Tell PF our max_frame size */
+ ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size);
for (int i = 0; i < adapter->num_queues; i++, rxr++) {
u64 rdba = rxr->rxdma.dma_paddr;
@@ -1670,7 +1670,7 @@ ixv_initialize_receive_units(struct adapter *adapter)
/* Disable the queue */
rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
- rxdctl &= ~(IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME);
+ rxdctl &= ~IXGBE_RXDCTL_ENABLE;
IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);
for (int j = 0; j < 10; j++) {
if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &
@@ -1700,17 +1700,11 @@ ixv_initialize_receive_units(struct adapter *adapter)
reg |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), reg);
- /* Setup the HW Rx Head and Tail Descriptor Pointers */
- IXGBE_WRITE_REG(hw, IXGBE_VFRDH(rxr->me), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),
- adapter->num_rx_desc - 1);
-
- /* Set Rx Tail register */
+ /* Capture Rx Tail register */
rxr->tail = IXGBE_VFRDT(rxr->me);
/* Do the queue enabling last */
- rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
- rxdctl |= IXGBE_RXDCTL_ENABLE;
+ rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);
for (int k = 0; k < 10; k++) {
if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &
@@ -1769,7 +1763,7 @@ ixv_setup_vlan_support(struct adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 ctrl, vid, vfta, retry;
-
+ struct rx_ring *rxr;
/*
** We get here thru init_locked, meaning
@@ -1785,6 +1779,12 @@ ixv_setup_vlan_support(struct adapter *adapter)
ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
ctrl |= IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl);
+ /*
+ * Let Rx path know that it needs to store VLAN tag
+ * as part of extra mbuf info.
+ */
+ rxr = &adapter->rx_rings[i];
+ rxr->vtag_strip = TRUE;
}
/*
@@ -1800,7 +1800,7 @@ ixv_setup_vlan_support(struct adapter *adapter)
** based on the bits set in each
** of the array ints.
*/
- for ( int j = 0; j < 32; j++) {
+ for (int j = 0; j < 32; j++) {
retry = 0;
if ((vfta & (1 << j)) == 0)
continue;
@@ -1827,10 +1827,10 @@ ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
struct adapter *adapter = ifp->if_softc;
u16 index, bit;
- if (ifp->if_softc != arg) /* Not our event */
+ if (ifp->if_softc != arg) /* Not our event */
return;
- if ((vtag == 0) || (vtag > 4095)) /* Invalid */
+ if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
IXGBE_CORE_LOCK(adapter);
diff --git a/sys/dev/ixgbe/ix_txrx.c b/sys/dev/ixgbe/ix_txrx.c
index 068048f..ef42714 100644
--- a/sys/dev/ixgbe/ix_txrx.c
+++ b/sys/dev/ixgbe/ix_txrx.c
@@ -80,27 +80,6 @@ static bool ixgbe_rsc_enable = FALSE;
static int atr_sample_rate = 20;
#endif
-/* Shared PCI config read/write */
-inline u16
-ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg)
-{
- u16 value;
-
- value = pci_read_config(((struct ixgbe_osdep *)hw->back)->dev,
- reg, 2);
-
- return (value);
-}
-
-inline void
-ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value)
-{
- pci_write_config(((struct ixgbe_osdep *)hw->back)->dev,
- reg, value, 2);
-
- return;
-}
-
/*********************************************************************
* Local Function prototypes
*********************************************************************/
@@ -186,8 +165,8 @@ ixgbe_start(struct ifnet *ifp)
/*
-** Multiqueue Transmit driver
-**
+** Multiqueue Transmit Entry Point
+** (if_transmit function)
*/
int
ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m)
@@ -210,10 +189,14 @@ ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m)
if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
#ifdef RSS
if (rss_hash2bucket(m->m_pkthdr.flowid,
- M_HASHTYPE_GET(m), &bucket_id) == 0)
- /* TODO: spit out something if bucket_id > num_queues? */
+ M_HASHTYPE_GET(m), &bucket_id) == 0) {
i = bucket_id % adapter->num_queues;
- else
+#ifdef IXGBE_DEBUG
+ if (bucket_id > adapter->num_queues)
+ if_printf(ifp, "bucket_id (%d) > num_queues "
+ "(%d)\n", bucket_id, adapter->num_queues);
+#endif
+ } else
#endif
i = m->m_pkthdr.flowid % adapter->num_queues;
} else
@@ -444,6 +427,7 @@ retry:
}
#endif
+ olinfo_status |= IXGBE_ADVTXD_CC;
i = txr->next_avail_desc;
for (j = 0; j < nsegs; j++) {
bus_size_t seglen;
@@ -736,8 +720,12 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
struct adapter *adapter = txr->adapter;
struct ixgbe_adv_tx_context_desc *TXD;
struct ether_vlan_header *eh;
+#ifdef INET
struct ip *ip;
+#endif
+#ifdef INET6
struct ip6_hdr *ip6;
+#endif
u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
int ehdrlen, ip_hlen = 0;
u16 etype;
@@ -745,9 +733,11 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
int offload = TRUE;
int ctxd = txr->next_avail_desc;
u16 vtag = 0;
+ caddr_t l3d;
+
/* First check if TSO is to be used */
- if (mp->m_pkthdr.csum_flags & CSUM_TSO)
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_TSO|CSUM_IP6_TSO))
return (ixgbe_tso_setup(txr, mp, cmd_type_len, olinfo_status));
if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)
@@ -790,20 +780,38 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
if (offload == FALSE)
goto no_offloads;
+ /*
+ * If the first mbuf only includes the ethernet header, jump to the next one
+ * XXX: This assumes the stack splits mbufs containing headers on header boundaries
+ * XXX: And assumes the entire IP header is contained in one mbuf
+ */
+ if (mp->m_len == ehdrlen && mp->m_next)
+ l3d = mtod(mp->m_next, caddr_t);
+ else
+ l3d = mtod(mp, caddr_t) + ehdrlen;
+
switch (etype) {
+#ifdef INET
case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + ehdrlen);
+ ip = (struct ip *)(l3d);
ip_hlen = ip->ip_hl << 2;
ipproto = ip->ip_p;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
+ /* Insert IPv4 checksum into data descriptors */
+ if (mp->m_pkthdr.csum_flags & CSUM_IP) {
+ ip->ip_sum = 0;
+ *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
+ }
break;
+#endif
+#ifdef INET6
case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
+ ip6 = (struct ip6_hdr *)(l3d);
ip_hlen = sizeof(struct ip6_hdr);
- /* XXX-BZ this will go badly in case of ext hdrs. */
ipproto = ip6->ip6_nxt;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
break;
+#endif
default:
offload = FALSE;
break;
@@ -811,29 +819,32 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
vlan_macip_lens |= ip_hlen;
+ /* No support for offloads for non-L4 next headers */
switch (ipproto) {
case IPPROTO_TCP:
- if (mp->m_pkthdr.csum_flags & CSUM_TCP)
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP))
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ else
+ offload = false;
break;
-
case IPPROTO_UDP:
- if (mp->m_pkthdr.csum_flags & CSUM_UDP)
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP))
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
+ else
+ offload = false;
break;
-
-#if __FreeBSD_version >= 800000
case IPPROTO_SCTP:
- if (mp->m_pkthdr.csum_flags & CSUM_SCTP)
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP))
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ else
+ offload = false;
break;
-#endif
default:
- offload = FALSE;
+ offload = false;
break;
}
- if (offload) /* For the TX descriptor setup */
+ if (offload) /* Insert L4 checksum into data descriptors */
*olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
no_offloads:
@@ -878,7 +889,6 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp,
#endif
struct tcphdr *th;
-
/*
* Determine where frame payload starts.
* Jump over vlan headers if already present
@@ -1035,7 +1045,7 @@ ixgbe_txeof(struct tx_ring *txr)
BUS_DMASYNC_POSTREAD);
do {
- union ixgbe_adv_tx_desc *eop= buf->eop;
+ union ixgbe_adv_tx_desc *eop = buf->eop;
if (eop == NULL) /* No work */
break;
@@ -1277,6 +1287,7 @@ ixgbe_setup_hw_rsc(struct rx_ring *rxr)
rxr->hw_rsc = TRUE;
}
+
/*********************************************************************
*
* Refresh mbuf buffers for RX descriptor rings
@@ -1412,7 +1423,6 @@ fail:
return (error);
}
-
static void
ixgbe_free_receive_ring(struct rx_ring *rxr)
{
@@ -1432,7 +1442,6 @@ ixgbe_free_receive_ring(struct rx_ring *rxr)
}
}
-
/*********************************************************************
*
* Initialize a receive ring and its buffers.
@@ -1980,34 +1989,28 @@ ixgbe_rx_checksum(u32 staterr, struct mbuf * mp, u32 ptype)
{
u16 status = (u16) staterr;
u8 errors = (u8) (staterr >> 24);
- bool sctp = FALSE;
+ bool sctp = false;
if ((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&
(ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0)
- sctp = TRUE;
+ sctp = true;
+ /* IPv4 checksum */
if (status & IXGBE_RXD_STAT_IPCS) {
- if (!(errors & IXGBE_RXD_ERR_IPE)) {
- /* IP Checksum Good */
- mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
- mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
-
- } else
- mp->m_pkthdr.csum_flags = 0;
+ mp->m_pkthdr.csum_flags |= CSUM_L3_CALC;
+ /* IP Checksum Good */
+ if (!(errors & IXGBE_RXD_ERR_IPE))
+ mp->m_pkthdr.csum_flags |= CSUM_L3_VALID;
}
+ /* TCP/UDP/SCTP checksum */
if (status & IXGBE_RXD_STAT_L4CS) {
- u64 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
-#if __FreeBSD_version >= 800000
- if (sctp)
- type = CSUM_SCTP_VALID;
-#endif
+ mp->m_pkthdr.csum_flags |= CSUM_L4_CALC;
if (!(errors & IXGBE_RXD_ERR_TCPE)) {
- mp->m_pkthdr.csum_flags |= type;
+ mp->m_pkthdr.csum_flags |= CSUM_L4_VALID;
if (!sctp)
mp->m_pkthdr.csum_data = htons(0xffff);
- }
+ }
}
- return;
}
/********************************************************************
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index f7721f6..008ced3 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -141,12 +141,6 @@
#define DBA_ALIGN 128
/*
- * This parameter controls the maximum no of times the driver will loop in
- * the isr. Minimum Value = 1
- */
-#define MAX_LOOP 10
-
-/*
* This is the max watchdog interval, ie. the time that can
* pass between any two TX clean operations, such only happening
* when the TX hardware is functioning.
@@ -162,9 +156,11 @@
/* These defines are used in MTU calculations */
#define IXGBE_MAX_FRAME_SIZE 9728
-#define IXGBE_MTU_HDR (ETHER_HDR_LEN + ETHER_CRC_LEN + \
+#define IXGBE_MTU_HDR (ETHER_HDR_LEN + ETHER_CRC_LEN)
+#define IXGBE_MTU_HDR_VLAN (ETHER_HDR_LEN + ETHER_CRC_LEN + \
ETHER_VLAN_ENCAP_LEN)
#define IXGBE_MAX_MTU (IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR)
+#define IXGBE_MAX_MTU_VLAN (IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR_VLAN)
/* Flow control constants */
#define IXGBE_FC_PAUSE 0xFFFF
@@ -181,6 +177,9 @@
* modern Intel CPUs, results in 40 bytes wasted and a significant drop
* in observed efficiency of the optimization, 97.9% -> 81.8%.
*/
+#if __FreeBSD_version < 1002000
+#define MPKTHSIZE (sizeof(struct m_hdr) + sizeof(struct pkthdr))
+#endif
#define IXGBE_RX_COPY_HDR_PADDED ((((MPKTHSIZE - 1) / 32) + 1) * 32)
#define IXGBE_RX_COPY_LEN (MSIZE - IXGBE_RX_COPY_HDR_PADDED)
#define IXGBE_RX_COPY_ALIGN (IXGBE_RX_COPY_HDR_PADDED - MPKTHSIZE)
@@ -211,7 +210,6 @@
#define MSIX_82598_BAR 3
#define MSIX_82599_BAR 4
#define IXGBE_TSO_SIZE 262140
-#define IXGBE_TX_BUFFER_SIZE ((u32) 1514)
#define IXGBE_RX_HDR 128
#define IXGBE_VFTA_SIZE 128
#define IXGBE_BR_SIZE 4096
@@ -221,8 +219,12 @@
#define IXV_EITR_DEFAULT 128
-/* Offload bits in mbuf flag */
-#if __FreeBSD_version >= 800000
+/* Supported offload bits in mbuf flag */
+#if __FreeBSD_version >= 1000000
+#define CSUM_OFFLOAD (CSUM_IP_TSO|CSUM_IP6_TSO|CSUM_IP| \
+ CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP| \
+ CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP)
+#elif __FreeBSD_version >= 800000
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP)
#else
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP)
@@ -243,7 +245,11 @@
#define IXGBE_LOW_LATENCY 128
#define IXGBE_AVE_LATENCY 400
#define IXGBE_BULK_LATENCY 1200
-#define IXGBE_LINK_ITR 2000
+
+/* Using 1FF (the max value), the interval is ~1.05ms */
+#define IXGBE_LINK_ITR_QUANTA 0x1FF
+#define IXGBE_LINK_ITR ((IXGBE_LINK_ITR_QUANTA << 3) & \
+ IXGBE_EITR_ITR_INT_MASK)
/* MAC type macros */
#define IXGBE_IS_X550VF(_adapter) \
@@ -449,11 +455,11 @@ struct ixgbe_vf {
/* Our adapter structure */
struct adapter {
- struct ifnet *ifp;
struct ixgbe_hw hw;
-
struct ixgbe_osdep osdep;
+
struct device *dev;
+ struct ifnet *ifp;
struct resource *pci_mem;
struct resource *msix_mem;
@@ -491,6 +497,7 @@ struct adapter {
u32 optics;
u32 fc; /* local flow ctrl setting */
int advertise; /* link speeds */
+ bool enable_aim; /* adaptive interrupt moderation */
bool link_active;
u16 max_frame_size;
u16 num_segs;
@@ -555,6 +562,10 @@ struct adapter {
#ifdef PCI_IOV
struct ixgbe_vf *vfs;
#endif
+#ifdef DEV_NETMAP
+ void (*init_locked)(struct adapter *);
+ void (*stop_locked)(void *);
+#endif
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c
index 46e64c5..c10e23a 100644
--- a/sys/dev/ixgbe/ixgbe_82598.c
+++ b/sys/dev/ixgbe/ixgbe_82598.c
@@ -660,7 +660,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
&adapt_comp_reg);
if (link_up_wait_to_complete) {
- for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ for (i = 0; i < hw->mac.max_link_up_time; i++) {
if ((link_reg & 1) &&
((adapt_comp_reg & 1) == 0)) {
*link_up = TRUE;
@@ -689,7 +689,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
if (link_up_wait_to_complete) {
- for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ for (i = 0; i < hw->mac.max_link_up_time; i++) {
if (links_reg & IXGBE_LINKS_UP) {
*link_up = TRUE;
break;
diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c
index b38620f..109ed95 100644
--- a/sys/dev/ixgbe/ixgbe_82599.c
+++ b/sys/dev/ixgbe/ixgbe_82599.c
@@ -382,8 +382,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES;
mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
- mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
- IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE;
+ mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
+ & IXGBE_FWSM_MODE_MASK);
hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
@@ -1370,7 +1370,7 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
* Continue setup of fdirctrl register bits:
* Turn perfect match filtering on
* Report hash in RSS field of Rx wb descriptor
- * Initialize the drop queue
+ * Initialize the drop queue to queue 127
* Move the flexible bytes to use the ethertype - shift 6 words
* Set the maximum length per hash bucket to 0xA filters
* Send interrupt when 64 (0x4 * 16) filters are left
@@ -1381,6 +1381,9 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
(0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
(0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
(4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
+ if ((hw->mac.type == ixgbe_mac_X550) ||
+ (hw->mac.type == ixgbe_mac_X550EM_x))
+ fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
if (cloud_mode)
fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD <<
@@ -1392,6 +1395,39 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
return IXGBE_SUCCESS;
}
+/**
+ * ixgbe_set_fdir_drop_queue_82599 - Set Flow Director drop queue
+ * @hw: pointer to hardware structure
+ * @dropqueue: Rx queue index used for the dropped packets
+ **/
+void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue)
+{
+ u32 fdirctrl;
+
+ DEBUGFUNC("ixgbe_set_fdir_drop_queue_82599");
+ /* Clear init done bit and drop queue field */
+ fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
+ fdirctrl &= ~(IXGBE_FDIRCTRL_DROP_Q_MASK | IXGBE_FDIRCTRL_INIT_DONE);
+
+ /* Set drop queue */
+ fdirctrl |= (dropqueue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
+ if ((hw->mac.type == ixgbe_mac_X550) ||
+ (hw->mac.type == ixgbe_mac_X550EM_x))
+ fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
+
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+ (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
+ IXGBE_FDIRCMD_CLEARHT));
+ IXGBE_WRITE_FLUSH(hw);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+ (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
+ ~IXGBE_FDIRCMD_CLEARHT));
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* write hashes and fdirctrl register, poll for completion */
+ ixgbe_fdir_enable_82599(hw, fdirctrl);
+}
+
/*
* These defines allow us to quickly generate all of the necessary instructions
* in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
@@ -1492,16 +1528,15 @@ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
* Note that the tunnel bit in input must not be set when the hardware
* tunneling support does not exist.
**/
-s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common,
- u8 queue)
+void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common,
+ u8 queue)
{
u64 fdirhashcmd;
u8 flow_type;
bool tunnel;
u32 fdircmd;
- s32 err;
DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
@@ -1523,7 +1558,7 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
break;
default:
DEBUGOUT(" Error on flow type input\n");
- return IXGBE_ERR_CONFIG;
+ return;
}
/* configure FDIRCMD register */
@@ -1542,15 +1577,9 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
- err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
- if (err) {
- DEBUGOUT("Flow Director command did not complete!\n");
- return err;
- }
-
DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
- return IXGBE_SUCCESS;
+ return;
}
#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c
index 9784e3c..0f4d973 100644
--- a/sys/dev/ixgbe/ixgbe_api.c
+++ b/sys/dev/ixgbe/ixgbe_api.c
@@ -35,8 +35,10 @@
#include "ixgbe_api.h"
#include "ixgbe_common.h"
+#define IXGBE_EMPTY_PARAM
+
static const u32 ixgbe_mvals_base[IXGBE_MVALS_IDX_LIMIT] = {
- IXGBE_MVALS_INIT()
+ IXGBE_MVALS_INIT(IXGBE_EMPTY_PARAM)
};
static const u32 ixgbe_mvals_X540[IXGBE_MVALS_IDX_LIMIT] = {
@@ -113,6 +115,7 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
}
+ hw->mac.max_link_up_time = IXGBE_LINK_UP_TIME;
return status;
}
@@ -187,6 +190,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
hw->mvals = ixgbe_mvals_X540;
break;
case IXGBE_DEV_ID_X550T:
+ case IXGBE_DEV_ID_X550T1:
hw->mac.type = ixgbe_mac_X550;
hw->mvals = ixgbe_mvals_X550;
break;
diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h
index 8c2c4a8..24d5070 100644
--- a/sys/dev/ixgbe/ixgbe_api.h
+++ b/sys/dev/ixgbe/ixgbe_api.h
@@ -148,10 +148,10 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
bool cloud_mode);
-s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common,
- u8 queue);
+void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common,
+ u8 queue);
s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
union ixgbe_atr_input *input_mask, bool cloud_mode);
s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
@@ -180,6 +180,7 @@ s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
u16 *val);
s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
u8 data);
+void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue);
s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val);
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c
index f0a0776..feb74f6 100644
--- a/sys/dev/ixgbe/ixgbe_common.c
+++ b/sys/dev/ixgbe/ixgbe_common.c
@@ -70,7 +70,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
{
struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
struct ixgbe_mac_info *mac = &hw->mac;
- u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
DEBUGFUNC("ixgbe_init_ops_generic");
@@ -188,6 +188,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_X540T1:
case IXGBE_DEV_ID_X540_BYPASS:
case IXGBE_DEV_ID_X550T:
+ case IXGBE_DEV_ID_X550T1:
case IXGBE_DEV_ID_X550EM_X_10G_T:
supported = TRUE;
break;
@@ -198,9 +199,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
break;
}
- ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
+ if (!supported) {
+ ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
"Device %x does not support flow control autoneg",
hw->device_id);
+ }
+
return supported;
}
@@ -1038,7 +1042,7 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
bus->lan_id = bus->func;
/* check for a port swap */
- reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+ reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
if (reg & IXGBE_FACTPS_LFS)
bus->func ^= 0x1;
}
@@ -1164,7 +1168,7 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
* Check for EEPROM present first.
* If not present leave as none
*/
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
if (eec & IXGBE_EEC_PRES) {
eeprom->type = ixgbe_eeprom_spi;
@@ -1725,14 +1729,14 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
status = IXGBE_ERR_SWFW_SYNC;
if (status == IXGBE_SUCCESS) {
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
/* Request EEPROM Access */
eec |= IXGBE_EEC_REQ;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
if (eec & IXGBE_EEC_GNT)
break;
usec_delay(5);
@@ -1741,7 +1745,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
/* Release if grant not acquired */
if (!(eec & IXGBE_EEC_GNT)) {
eec &= ~IXGBE_EEC_REQ;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
DEBUGOUT("Could not acquire EEPROM grant\n");
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
@@ -1752,7 +1756,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
if (status == IXGBE_SUCCESS) {
/* Clear CS and SK */
eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
}
@@ -1782,7 +1786,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
if (!(swsm & IXGBE_SWSM_SMBI)) {
status = IXGBE_SUCCESS;
break;
@@ -1807,7 +1811,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
if (!(swsm & IXGBE_SWSM_SMBI))
status = IXGBE_SUCCESS;
}
@@ -1815,17 +1819,17 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
/* Now get the semaphore between SW/FW through the SWESMBI bit */
if (status == IXGBE_SUCCESS) {
for (i = 0; i < timeout; i++) {
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
/* Set the SW EEPROM semaphore bit to request access */
swsm |= IXGBE_SWSM_SWESMBI;
- IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+ IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
/*
* If we set the bit successfully then we got the
* semaphore.
*/
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
if (swsm & IXGBE_SWSM_SWESMBI)
break;
@@ -1922,15 +1926,15 @@ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
DEBUGFUNC("ixgbe_standby_eeprom");
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
/* Toggle CS to flush commands */
eec |= IXGBE_EEC_CS;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
eec &= ~IXGBE_EEC_CS;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
}
@@ -1950,7 +1954,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
/*
* Mask is used to shift "count" bits of "data" out to the EEPROM
@@ -1971,7 +1975,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
else
eec &= ~IXGBE_EEC_DI;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
@@ -1988,7 +1992,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
/* We leave the "DI" bit set to "0" when we leave this routine. */
eec &= ~IXGBE_EEC_DI;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
IXGBE_WRITE_FLUSH(hw);
}
@@ -2011,7 +2015,7 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
* the value of the "DO" bit. During this "shifting in" process the
* "DI" bit should always be clear.
*/
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
@@ -2019,7 +2023,7 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
data = data << 1;
ixgbe_raise_eeprom_clk(hw, &eec);
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
eec &= ~(IXGBE_EEC_DI);
if (eec & IXGBE_EEC_DO)
@@ -2045,7 +2049,7 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
* (setting the SK bit), then delay
*/
*eec = *eec | IXGBE_EEC_SK;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
}
@@ -2064,7 +2068,7 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
* delay
*/
*eec = *eec & ~IXGBE_EEC_SK;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
}
@@ -2079,19 +2083,19 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
DEBUGFUNC("ixgbe_release_eeprom");
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
eec |= IXGBE_EEC_CS; /* Pull CS high */
eec &= ~IXGBE_EEC_SK; /* Lower SCK */
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
IXGBE_WRITE_FLUSH(hw);
usec_delay(1);
/* Stop requesting EEPROM access */
eec &= ~IXGBE_EEC_REQ;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
@@ -3147,6 +3151,9 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ if (hw->mac.type >= ixgbe_mac_X550)
+ goto out;
+
/*
* Before proceeding, make sure that the PCIe block does not have
* transactions pending.
@@ -4069,7 +4076,7 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
}
if (link_up_wait_to_complete) {
- for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ for (i = 0; i < hw->mac.max_link_up_time; i++) {
if (links_reg & IXGBE_LINKS_UP) {
*link_up = TRUE;
break;
@@ -4715,7 +4722,7 @@ bool ixgbe_mng_present(struct ixgbe_hw *hw)
if (hw->mac.type < ixgbe_mac_82599EB)
return FALSE;
- fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+ fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
fwsm &= IXGBE_FWSM_MODE_MASK;
return fwsm == IXGBE_FWSM_FW_MODE_PT;
}
@@ -4730,7 +4737,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
{
u32 fwsm, manc, factps;
- fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+ fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
return FALSE;
@@ -4739,7 +4746,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
return FALSE;
if (hw->mac.type <= ixgbe_mac_X540) {
- factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+ factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
if (factps & IXGBE_FACTPS_MNGCG)
return FALSE;
}
diff --git a/sys/dev/ixgbe/ixgbe_dcb.c b/sys/dev/ixgbe/ixgbe_dcb.c
index 3659d17..437d336 100644
--- a/sys/dev/ixgbe/ixgbe_dcb.c
+++ b/sys/dev/ixgbe/ixgbe_dcb.c
@@ -148,6 +148,11 @@ s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *hw,
/* Calculate credit refill ratio using multiplier */
credit_refill = min(link_percentage * min_multiplier,
(u32)IXGBE_DCB_MAX_CREDIT_REFILL);
+
+ /* Refill at least minimum credit */
+ if (credit_refill < min_credit)
+ credit_refill = min_credit;
+
p->data_credits_refill = (u16)credit_refill;
/* Calculate maximum credit for the TC */
@@ -158,7 +163,7 @@ s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *hw,
* of a TC is too small, the maximum credit may not be
* enough to send out a jumbo frame in data plane arbitration.
*/
- if (credit_max && (credit_max < min_credit))
+ if (credit_max < min_credit)
credit_max = min_credit;
if (direction == IXGBE_DCB_TX_CONFIG) {
diff --git a/sys/dev/ixgbe/LICENSE b/sys/dev/ixgbe/ixgbe_osdep.c
index 394b094..6a4e2fc 100644
--- a/sys/dev/ixgbe/LICENSE
+++ b/sys/dev/ixgbe/ixgbe_osdep.c
@@ -31,3 +31,58 @@
******************************************************************************/
/*$FreeBSD$*/
+
+#include "ixgbe_osdep.h"
+#include "ixgbe.h"
+
+inline device_t
+ixgbe_dev_from_hw(struct ixgbe_hw *hw)
+{
+ return ((struct adapter *)hw->back)->dev;
+}
+
+inline u16
+ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg)
+{
+ return pci_read_config(((struct adapter *)hw->back)->dev,
+ reg, 2);
+}
+
+inline void
+ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value)
+{
+ pci_write_config(((struct adapter *)hw->back)->dev,
+ reg, value, 2);
+}
+
+inline u32
+ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg)
+{
+ return bus_space_read_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+ ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+ reg);
+}
+
+inline void
+ixgbe_write_reg(struct ixgbe_hw *hw, u32 reg, u32 val)
+{
+ bus_space_write_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+ ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+ reg, val);
+}
+
+inline u32
+ixgbe_read_reg_array(struct ixgbe_hw *hw, u32 reg, u32 offset)
+{
+ return bus_space_read_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+ ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+ reg + (offset << 2));
+}
+
+inline void
+ixgbe_write_reg_array(struct ixgbe_hw *hw, u32 reg, u32 offset, u32 val)
+{
+ bus_space_write_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+ ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+ reg + (offset << 2), val);
+}
diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h
index 95f6ed5c..79d1166 100644
--- a/sys/dev/ixgbe/ixgbe_osdep.h
+++ b/sys/dev/ixgbe/ixgbe_osdep.h
@@ -57,11 +57,20 @@
#define ASSERT(x) if(!(x)) panic("IXGBE: x")
#define EWARN(H, W, S) printf(W)
+enum {
+ IXGBE_ERROR_SOFTWARE,
+ IXGBE_ERROR_POLLING,
+ IXGBE_ERROR_INVALID_STATE,
+ IXGBE_ERROR_UNSUPPORTED,
+ IXGBE_ERROR_ARGUMENT,
+ IXGBE_ERROR_CAUTION,
+};
+
/* The happy-fun DELAY macro is defined in /usr/src/sys/i386/include/clock.h */
#define usec_delay(x) DELAY(x)
#define msec_delay(x) DELAY(1000*(x))
-#define DBG 0
+#define DBG 0
#define MSGOUT(S, A, B) printf(S "\n", A, B)
#define DEBUGFUNC(F) DEBUGOUT(F);
#if DBG
@@ -73,9 +82,23 @@
#define DEBUGOUT5(S,A,B,C,D,E) printf(S "\n",A,B,C,D,E)
#define DEBUGOUT6(S,A,B,C,D,E,F) printf(S "\n",A,B,C,D,E,F)
#define DEBUGOUT7(S,A,B,C,D,E,F,G) printf(S "\n",A,B,C,D,E,F,G)
- #define ERROR_REPORT1(S,A) printf(S "\n",A)
- #define ERROR_REPORT2(S,A,B) printf(S "\n",A,B)
- #define ERROR_REPORT3(S,A,B,C) printf(S "\n",A,B,C)
+ #define ERROR_REPORT1 ERROR_REPORT
+ #define ERROR_REPORT2 ERROR_REPORT
+ #define ERROR_REPORT3 ERROR_REPORT
+ #define ERROR_REPORT(level, format, arg...) do { \
+ switch (level) { \
+ case IXGBE_ERROR_SOFTWARE: \
+ case IXGBE_ERROR_CAUTION: \
+ case IXGBE_ERROR_POLLING: \
+ case IXGBE_ERROR_INVALID_STATE: \
+ case IXGBE_ERROR_UNSUPPORTED: \
+ case IXGBE_ERROR_ARGUMENT: \
+ device_printf(ixgbe_dev_from_hw(hw), format, ## arg); \
+ break; \
+ default: \
+ break; \
+ } \
+ } while (0)
#else
#define DEBUGOUT(S)
#define DEBUGOUT1(S,A)
@@ -165,7 +188,7 @@ void prefetch(void *x)
* non-overlapping regions and 32-byte padding on both src and dst.
*/
static __inline int
-ixgbe_bcopy(void *_src, void *_dst, int l)
+ixgbe_bcopy(void *restrict _src, void *restrict _dst, int l)
{
uint64_t *src = _src;
uint64_t *dst = _dst;
@@ -183,11 +206,13 @@ struct ixgbe_osdep
{
bus_space_tag_t mem_bus_space_tag;
bus_space_handle_t mem_bus_space_handle;
- struct device *dev;
};
-/* These routines are needed by the shared code */
+/* These routines need struct ixgbe_hw declared */
struct ixgbe_hw;
+device_t ixgbe_dev_from_hw(struct ixgbe_hw *hw);
+
+/* These routines are needed by the shared code */
extern u16 ixgbe_read_pci_cfg(struct ixgbe_hw *, u32);
#define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg
@@ -196,26 +221,18 @@ extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, u32, u16);
#define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
-#define IXGBE_READ_REG(a, reg) (\
- bus_space_read_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \
- ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \
- reg))
-
-#define IXGBE_WRITE_REG(a, reg, value) (\
- bus_space_write_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \
- ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \
- reg, value))
-
+extern u32 ixgbe_read_reg(struct ixgbe_hw *, u32);
+#define IXGBE_READ_REG(a, reg) ixgbe_read_reg(a, reg)
-#define IXGBE_READ_REG_ARRAY(a, reg, offset) (\
- bus_space_read_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \
- ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \
- (reg + ((offset) << 2))))
+extern void ixgbe_write_reg(struct ixgbe_hw *, u32, u32);
+#define IXGBE_WRITE_REG(a, reg, val) ixgbe_write_reg(a, reg, val)
-#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) (\
- bus_space_write_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \
- ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \
- (reg + ((offset) << 2)), value))
+extern u32 ixgbe_read_reg_array(struct ixgbe_hw *, u32, u32);
+#define IXGBE_READ_REG_ARRAY(a, reg, offset) \
+ ixgbe_read_reg_array(a, reg, offset)
+extern void ixgbe_write_reg_array(struct ixgbe_hw *, u32, u32, u32);
+#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, val) \
+ ixgbe_write_reg_array(a, reg, offset, val)
#endif /* _IXGBE_OS_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c
index 88206c7..f5d22b2 100644
--- a/sys/dev/ixgbe/ixgbe_phy.c
+++ b/sys/dev/ixgbe/ixgbe_phy.c
@@ -508,7 +508,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
break;
- case X550_PHY_ID:
+ case X550_PHY_ID1:
+ case X550_PHY_ID2:
+ case X550_PHY_ID3:
case X540_PHY_ID:
phy_type = ixgbe_phy_aq;
break;
@@ -830,7 +832,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
if (hw->mac.type == ixgbe_mac_X550) {
if (speed & IXGBE_LINK_SPEED_5GB_FULL) {
- /* Set or unset auto-negotiation 1G advertisement */
+ /* Set or unset auto-negotiation 5G advertisement */
hw->phy.ops.read_reg(hw,
IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
@@ -848,7 +850,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
}
if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) {
- /* Set or unset auto-negotiation 1G advertisement */
+ /* Set or unset auto-negotiation 2.5G advertisement */
hw->phy.ops.read_reg(hw,
IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
@@ -950,54 +952,70 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
/* Setup link based on the new speed settings */
- hw->phy.ops.setup_link(hw);
+ ixgbe_setup_phy_link(hw);
return IXGBE_SUCCESS;
}
/**
- * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
- * @hw: pointer to hardware structure
- * @speed: pointer to link speed
- * @autoneg: boolean auto-negotiation value
+ * ixgbe_get_copper_speeds_supported - Get copper link speeds from phy
+ * @hw: pointer to hardware structure
*
- * Determines the supported link capabilities by reading the PHY auto
- * negotiation register.
+ * Determines the supported link capabilities by reading the PHY auto
+ * negotiation register.
**/
-s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
- ixgbe_link_speed *speed,
- bool *autoneg)
+static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
{
s32 status;
u16 speed_ability;
- DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
-
- *speed = 0;
- *autoneg = TRUE;
-
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&speed_ability);
+ if (status)
+ return status;
- if (status == IXGBE_SUCCESS) {
- if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
- *speed |= IXGBE_LINK_SPEED_10GB_FULL;
- if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
- *speed |= IXGBE_LINK_SPEED_1GB_FULL;
- if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
- *speed |= IXGBE_LINK_SPEED_100_FULL;
+ if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
+ if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_X550:
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
+ break;
+ case ixgbe_mac_X550EM_x:
+ hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
+ break;
+ default:
+ break;
}
- /* Internal PHY does not support 100 Mbps */
- if (hw->mac.type == ixgbe_mac_X550EM_x)
- *speed &= ~IXGBE_LINK_SPEED_100_FULL;
+ return status;
+}
+
+/**
+ * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: boolean auto-negotiation value
+ **/
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg)
+{
+ s32 status = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
- if (hw->mac.type == ixgbe_mac_X550) {
- *speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
- *speed |= IXGBE_LINK_SPEED_5GB_FULL;
- }
+ *autoneg = TRUE;
+ if (!hw->phy.speeds_supported)
+ status = ixgbe_get_copper_speeds_supported(hw);
+ *speed = hw->phy.speeds_supported;
return status;
}
@@ -2716,6 +2734,9 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
u32 status;
u16 reg;
+ if (!on && ixgbe_mng_present(hw))
+ return 0;
+
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
&reg);
diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h
index fad31bd..3713e28 100644
--- a/sys/dev/ixgbe/ixgbe_phy.h
+++ b/sys/dev/ixgbe/ixgbe_phy.h
@@ -92,16 +92,23 @@
#define IXGBE_CS4227_GLOBAL_ID_LSB 0
#define IXGBE_CS4227_SCRATCH 2
#define IXGBE_CS4227_GLOBAL_ID_VALUE 0x03E5
-#define IXGBE_CS4227_SCRATCH_VALUE 0x5aa5
-#define IXGBE_CS4227_RETRIES 5
+#define IXGBE_CS4227_RESET_PENDING 0x1357
+#define IXGBE_CS4227_RESET_COMPLETE 0x5AA5
+#define IXGBE_CS4227_RETRIES 15
+#define IXGBE_CS4227_EFUSE_STATUS 0x0181
#define IXGBE_CS4227_LINE_SPARE22_MSB 0x12AD /* Reg to program speed */
#define IXGBE_CS4227_LINE_SPARE24_LSB 0x12B0 /* Reg to program EDC */
#define IXGBE_CS4227_HOST_SPARE22_MSB 0x1AAD /* Reg to program speed */
#define IXGBE_CS4227_HOST_SPARE24_LSB 0x1AB0 /* Reg to program EDC */
+#define IXGBE_CS4227_EEPROM_STATUS 0x5001
+#define IXGBE_CS4227_EEPROM_LOAD_OK 0x0001
+#define IXGBE_CS4227_SPEED_1G 0x8000
+#define IXGBE_CS4227_SPEED_10G 0
#define IXGBE_CS4227_EDC_MODE_CX1 0x0002
#define IXGBE_CS4227_EDC_MODE_SR 0x0004
+#define IXGBE_CS4227_EDC_MODE_DIAG 0x0008
#define IXGBE_CS4227_RESET_HOLD 500 /* microseconds */
-#define IXGBE_CS4227_RESET_DELAY 500 /* milliseconds */
+#define IXGBE_CS4227_RESET_DELAY 450 /* milliseconds */
#define IXGBE_CS4227_CHECK_DELAY 30 /* milliseconds */
#define IXGBE_PE 0xE0 /* Port expander address */
#define IXGBE_PE_OUTPUT 1 /* Output register offset */
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index 2a53952..da03f79 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -131,6 +131,7 @@
#define IXGBE_DEV_ID_X540_BYPASS 0x155C
#define IXGBE_DEV_ID_X540T1 0x1560
#define IXGBE_DEV_ID_X550T 0x1563
+#define IXGBE_DEV_ID_X550T1 0x15D1
#define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA
#define IXGBE_DEV_ID_X550EM_X_KR 0x15AB
#define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC
@@ -1478,7 +1479,10 @@ struct ixgbe_dmac_config {
#define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK 0xFF01 /* int chip-wide mask */
#define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG 0xFC01 /* int chip-wide mask */
#define IXGBE_MDIO_GLOBAL_ALARM_1 0xCC00 /* Global alarm 1 */
+#define IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT 0x0010 /* device fault */
#define IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL 0x4000 /* high temp failure */
+#define IXGBE_MDIO_GLOBAL_FAULT_MSG 0xC850 /* Global Fault Message */
+#define IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP 0x8007 /* high temp failure */
#define IXGBE_MDIO_GLOBAL_INT_MASK 0xD400 /* Global int mask */
#define IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN 0x1000 /* autoneg vendor alarm int enable */
#define IXGBE_MDIO_GLOBAL_ALARM_1_INT 0x4 /* int in Global alarm 1 */
@@ -1544,7 +1548,9 @@ struct ixgbe_dmac_config {
#define TN1010_PHY_ID 0x00A19410
#define TNX_FW_REV 0xB
#define X540_PHY_ID 0x01540200
-#define X550_PHY_ID 0x01540220
+#define X550_PHY_ID1 0x01540220
+#define X550_PHY_ID2 0x01540223
+#define X550_PHY_ID3 0x01540221
#define X557_PHY_ID 0x01540240
#define AQ_FW_REV 0x20
#define QT2022_PHY_ID 0x0043A400
@@ -1937,6 +1943,7 @@ enum {
* FIP (0x8914): Filter 4
* LLDP (0x88CC): Filter 5
* LACP (0x8809): Filter 6
+ * FC (0x8808): Filter 7
*/
#define IXGBE_ETQF_FILTER_EAPOL 0
#define IXGBE_ETQF_FILTER_FCOE 2
@@ -1944,6 +1951,7 @@ enum {
#define IXGBE_ETQF_FILTER_FIP 4
#define IXGBE_ETQF_FILTER_LLDP 5
#define IXGBE_ETQF_FILTER_LACP 6
+#define IXGBE_ETQF_FILTER_FC 7
/* VLAN Control Bit Masks */
#define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */
#define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */
@@ -2803,7 +2811,9 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIRCTRL_REPORT_STATUS 0x00000020
#define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080
#define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8
+#define IXGBE_FDIRCTRL_DROP_Q_MASK 0x00007F00
#define IXGBE_FDIRCTRL_FLEX_SHIFT 16
+#define IXGBE_FDIRCTRL_DROP_NO_MATCH 0x00008000
#define IXGBE_FDIRCTRL_FILTERMODE_SHIFT 21
#define IXGBE_FDIRCTRL_FILTERMODE_MACVLAN 0x0001 /* bit 23:21, 001b */
#define IXGBE_FDIRCTRL_FILTERMODE_CLOUD 0x0002 /* bit 23:21, 010b */
@@ -2907,6 +2917,11 @@ enum ixgbe_fdir_pballoc_type {
#define FW_DISABLE_RXEN_CMD 0xDE
#define FW_DISABLE_RXEN_LEN 0x1
#define FW_PHY_MGMT_REQ_CMD 0x20
+#define FW_INT_PHY_REQ_CMD 0xB
+#define FW_INT_PHY_REQ_LEN 10
+#define FW_INT_PHY_REQ_READ 0
+#define FW_INT_PHY_REQ_WRITE 1
+
/* Host Interface Command Structures */
struct ixgbe_hic_hdr {
@@ -2975,6 +2990,21 @@ struct ixgbe_hic_disable_rxen {
u16 pad3;
};
+struct ixgbe_hic_internal_phy_req {
+ struct ixgbe_hic_hdr hdr;
+ u8 port_number;
+ u8 command_type;
+ u16 address;
+ u16 rsv1;
+ u32 write_data;
+ u16 pad;
+};
+
+struct ixgbe_hic_internal_phy_resp {
+ struct ixgbe_hic_hdr hdr;
+ u32 read_data;
+};
+
/* Transmit Descriptor - Legacy */
struct ixgbe_legacy_tx_desc {
@@ -3310,6 +3340,7 @@ union ixgbe_atr_hash_dword {
IXGBE_CAT(SRAMREL, m), \
IXGBE_CAT(FACTPS, m), \
IXGBE_CAT(SWSM, m), \
+ IXGBE_CAT(SWFW_SYNC, m), \
IXGBE_CAT(FWSM, m), \
IXGBE_CAT(SDP0_GPIEN, m), \
IXGBE_CAT(SDP1_GPIEN, m), \
@@ -3792,6 +3823,7 @@ struct ixgbe_mac_info {
u8 flags;
struct ixgbe_dmac_config dmac_config;
bool set_lben;
+ u32 max_link_up_time;
};
struct ixgbe_phy_info {
@@ -3806,6 +3838,7 @@ struct ixgbe_phy_info {
u32 phy_semaphore_mask;
bool reset_disable;
ixgbe_autoneg_advertised autoneg_advertised;
+ ixgbe_link_speed speeds_supported;
enum ixgbe_smart_speed smart_speed;
bool smart_speed_active;
bool multispeed_fiber;
@@ -3918,15 +3951,15 @@ struct ixgbe_hw {
#define IXGBE_FUSES0_300MHZ (1 << 5)
#define IXGBE_FUSES0_REV1 (1 << 6)
-#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P == 0) ? (0x4010) : (0x8010))
-#define IXGBE_KRM_LINK_CTRL_1(P) ((P == 0) ? (0x420C) : (0x820C))
-#define IXGBE_KRM_AN_CNTL_1(P) ((P == 0) ? (0x422C) : (0x822C))
-#define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P == 0) ? (0x4634) : (0x8634))
-#define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P == 0) ? (0x4638) : (0x8638))
-#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P == 0) ? (0x4B00) : (0x8B00))
-#define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P == 0) ? (0x4E00) : (0x8E00))
-#define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P == 0) ? (0x5520) : (0x9520))
-#define IXGBE_KRM_RX_ANA_CTL(P) ((P == 0) ? (0x5A00) : (0x9A00))
+#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010)
+#define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C)
+#define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C)
+#define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
+#define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638)
+#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00)
+#define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P) ? 0x8E00 : 0x4E00)
+#define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520)
+#define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00)
#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B (1 << 9)
#define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS (1 << 11)
@@ -3960,15 +3993,6 @@ struct ixgbe_hw {
#define IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN (1 << 3)
#define IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN (1 << 31)
-#define IXGBE_KX4_LINK_CNTL_1 0x4C
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX (1 << 16)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 (1 << 17)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX (1 << 24)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX4 (1 << 25)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE (1 << 29)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_FORCE_LINK_UP (1 << 30)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART (1 << 31)
-
#define IXGBE_SB_IOSF_INDIRECT_CTRL 0x00011144
#define IXGBE_SB_IOSF_INDIRECT_DATA 0x00011148
@@ -3985,8 +4009,6 @@ struct ixgbe_hw {
#define IXGBE_SB_IOSF_CTRL_BUSY_SHIFT 31
#define IXGBE_SB_IOSF_CTRL_BUSY (1 << IXGBE_SB_IOSF_CTRL_BUSY_SHIFT)
#define IXGBE_SB_IOSF_TARGET_KR_PHY 0
-#define IXGBE_SB_IOSF_TARGET_KX4_PHY 1
-#define IXGBE_SB_IOSF_TARGET_KX4_PCS 2
#define IXGBE_NW_MNG_IF_SEL 0x00011178
#define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24)
diff --git a/sys/dev/ixgbe/ixgbe_vf.c b/sys/dev/ixgbe/ixgbe_vf.c
index a00b8be..2ce4d32 100644
--- a/sys/dev/ixgbe/ixgbe_vf.c
+++ b/sys/dev/ixgbe/ixgbe_vf.c
@@ -225,8 +225,6 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
if (ret_val)
return ret_val;
- msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
-
if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK) &&
msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK))
return IXGBE_ERR_INVALID_MAC_ADDR;
diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c
index ddf0674..fd52ebe 100644
--- a/sys/dev/ixgbe/ixgbe_x540.c
+++ b/sys/dev/ixgbe/ixgbe_x540.c
@@ -82,8 +82,7 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
/* PHY */
phy->ops.init = ixgbe_init_phy_ops_generic;
phy->ops.reset = NULL;
- if (!ixgbe_mng_present(hw))
- phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
+ phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
/* MAC */
mac->ops.reset_hw = ixgbe_reset_hw_X540;
@@ -138,8 +137,8 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
* ARC supported; valid only if manageability features are
* enabled.
*/
- mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
- IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE;
+ mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
+ & IXGBE_FWSM_MODE_MASK);
hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
@@ -356,7 +355,7 @@ s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
eeprom->semaphore_delay = 10;
eeprom->type = ixgbe_flash;
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
IXGBE_EEC_SIZE_SHIFT);
eeprom->word_size = 1 << (eeprom_size +
@@ -681,8 +680,8 @@ s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
goto out;
}
- flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+ flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)) | IXGBE_EEC_FLUP;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
status = ixgbe_poll_flash_update_done_X540(hw);
if (status == IXGBE_SUCCESS)
@@ -691,11 +690,11 @@ s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
DEBUGOUT("Flash update time out\n");
if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) {
- flup = IXGBE_READ_REG(hw, IXGBE_EEC);
+ flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
if (flup & IXGBE_EEC_SEC1VAL) {
flup |= IXGBE_EEC_FLUP;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
}
status = ixgbe_poll_flash_update_done_X540(hw);
@@ -724,7 +723,7 @@ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
- reg = IXGBE_READ_REG(hw, IXGBE_EEC);
+ reg = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
if (reg & IXGBE_EEC_FLUDONE) {
status = IXGBE_SUCCESS;
break;
@@ -775,10 +774,11 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
if (ixgbe_get_swfw_sync_semaphore(hw))
return IXGBE_ERR_SWFW_SYNC;
- swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
if (!(swfw_sync & (fwmask | swmask | hwmask))) {
swfw_sync |= swmask;
- IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw),
+ swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
msec_delay(5);
return IXGBE_SUCCESS;
@@ -805,10 +805,10 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
*/
if (ixgbe_get_swfw_sync_semaphore(hw))
return IXGBE_ERR_SWFW_SYNC;
- swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
if (swfw_sync & (fwmask | hwmask)) {
swfw_sync |= swmask;
- IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
msec_delay(5);
return IXGBE_SUCCESS;
@@ -852,9 +852,9 @@ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
swmask |= mask & IXGBE_GSSR_I2C_MASK;
ixgbe_get_swfw_sync_semaphore(hw);
- swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
swfw_sync &= ~swmask;
- IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
ixgbe_release_swfw_sync_semaphore(hw);
msec_delay(5);
@@ -881,7 +881,7 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
if (!(swsm & IXGBE_SWSM_SMBI)) {
status = IXGBE_SUCCESS;
break;
@@ -892,7 +892,7 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
/* Now get the semaphore between SW/FW through the REGSMP bit */
if (status == IXGBE_SUCCESS) {
for (i = 0; i < timeout; i++) {
- swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
if (!(swsm & IXGBE_SWFW_REGSMP))
break;
@@ -932,13 +932,13 @@ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
- swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
swsm &= ~IXGBE_SWFW_REGSMP;
- IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swsm);
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
swsm &= ~IXGBE_SWSM_SMBI;
- IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+ IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
IXGBE_WRITE_FLUSH(hw);
}
diff --git a/sys/dev/ixgbe/ixgbe_x550.c b/sys/dev/ixgbe/ixgbe_x550.c
index 65daa17..1199d38 100644
--- a/sys/dev/ixgbe/ixgbe_x550.c
+++ b/sys/dev/ixgbe/ixgbe_x550.c
@@ -115,119 +115,6 @@ static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
}
/**
- * ixgbe_get_cs4227_status - Return CS4227 status
- * @hw: pointer to hardware structure
- *
- * Returns error if CS4227 not successfully initialized
- **/
-static s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw)
-{
- s32 status;
- u16 value = 0;
- u16 reg_slice, reg_val;
- u8 retry;
-
- for (retry = 0; retry < IXGBE_CS4227_RETRIES; ++retry) {
- status = ixgbe_read_cs4227(hw, IXGBE_CS4227_GLOBAL_ID_LSB,
- &value);
- if (status != IXGBE_SUCCESS)
- return status;
- if (value == IXGBE_CS4227_GLOBAL_ID_VALUE)
- break;
- msec_delay(IXGBE_CS4227_CHECK_DELAY);
- }
- if (value != IXGBE_CS4227_GLOBAL_ID_VALUE)
- return IXGBE_ERR_PHY;
-
- status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
- if (status != IXGBE_SUCCESS)
- return status;
-
- /* If this is the first time after power-on, check the ucode.
- * Otherwise, this will disrupt link on all ports. Because we
- * can only do this the first time, we must check all ports,
- * not just our own.
- */
- if (value != IXGBE_CS4227_SCRATCH_VALUE) {
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB;
- reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- status = ixgbe_write_cs4227(hw, reg_slice,
- reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
-
- reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB;
- reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- status = ixgbe_write_cs4227(hw, reg_slice,
- reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
-
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12);
- reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- status = ixgbe_write_cs4227(hw, reg_slice,
- reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
-
- reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12);
- reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- status = ixgbe_write_cs4227(hw, reg_slice,
- reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
-
- msec_delay(10);
- }
-
- /* Verify that the ucode is operational on all ports. */
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB;
- reg_val = 0xFFFF;
- status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
- if (reg_val != 0)
- return IXGBE_ERR_PHY;
-
- reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB;
- reg_val = 0xFFFF;
- status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
- if (reg_val != 0)
- return IXGBE_ERR_PHY;
-
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12);
- reg_val = 0xFFFF;
- status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
- if (reg_val != 0)
- return IXGBE_ERR_PHY;
-
- reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12);
- reg_val = 0xFFFF;
- status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
- if (status != IXGBE_SUCCESS)
- return status;
- if (reg_val != 0)
- return IXGBE_ERR_PHY;
-
- /* Set scratch for next time. */
- status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
- IXGBE_CS4227_SCRATCH_VALUE);
- if (status != IXGBE_SUCCESS)
- return status;
- status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
- if (status != IXGBE_SUCCESS)
- return status;
- if (value != IXGBE_CS4227_SCRATCH_VALUE)
- return IXGBE_ERR_PHY;
-
- return IXGBE_SUCCESS;
-}
-
-/**
* ixgbe_read_pe - Read register from port expander
* @hw: pointer to hardware structure
* @reg: register number to read
@@ -269,13 +156,17 @@ static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value)
* ixgbe_reset_cs4227 - Reset CS4227 using port expander
* @hw: pointer to hardware structure
*
+ * This function assumes that the caller has acquired the proper semaphore.
* Returns error code
**/
static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
{
s32 status;
+ u32 retry;
+ u16 value;
u8 reg;
+ /* Trigger hard reset. */
status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
if (status != IXGBE_SUCCESS)
return status;
@@ -310,7 +201,29 @@ static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
if (status != IXGBE_SUCCESS)
return status;
+ /* Wait for the reset to complete. */
msec_delay(IXGBE_CS4227_RESET_DELAY);
+ for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
+ &value);
+ if (status == IXGBE_SUCCESS &&
+ value == IXGBE_CS4227_EEPROM_LOAD_OK)
+ break;
+ msec_delay(IXGBE_CS4227_CHECK_DELAY);
+ }
+ if (retry == IXGBE_CS4227_RETRIES) {
+ ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+ "CS4227 reset did not complete.");
+ return IXGBE_ERR_PHY;
+ }
+
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
+ if (status != IXGBE_SUCCESS ||
+ !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
+ ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+ "CS4227 EEPROM did not load successfully.");
+ return IXGBE_ERR_PHY;
+ }
return IXGBE_SUCCESS;
}
@@ -321,29 +234,75 @@ static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
**/
static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
{
+ s32 status = IXGBE_SUCCESS;
u32 swfw_mask = hw->phy.phy_semaphore_mask;
- s32 status;
+ u16 value = 0;
u8 retry;
for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
if (status != IXGBE_SUCCESS) {
ERROR_REPORT2(IXGBE_ERROR_CAUTION,
- "semaphore failed with %d\n", status);
- return;
+ "semaphore failed with %d", status);
+ msec_delay(IXGBE_CS4227_CHECK_DELAY);
+ continue;
}
- status = ixgbe_get_cs4227_status(hw);
- if (status == IXGBE_SUCCESS) {
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
- msec_delay(hw->eeprom.semaphore_delay);
+
+ /* Get status of reset flow. */
+ status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
+
+ if (status == IXGBE_SUCCESS &&
+ value == IXGBE_CS4227_RESET_COMPLETE)
+ goto out;
+
+ if (status != IXGBE_SUCCESS ||
+ value != IXGBE_CS4227_RESET_PENDING)
+ break;
+
+ /* Reset is pending. Wait and check again. */
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msec_delay(IXGBE_CS4227_CHECK_DELAY);
+ }
+
+ /* If still pending, assume other instance failed. */
+ if (retry == IXGBE_CS4227_RETRIES) {
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+ if (status != IXGBE_SUCCESS) {
+ ERROR_REPORT2(IXGBE_ERROR_CAUTION,
+ "semaphore failed with %d", status);
return;
}
- ixgbe_reset_cs4227(hw);
- hw->mac.ops.release_swfw_sync(hw, swfw_mask);
- msec_delay(hw->eeprom.semaphore_delay);
}
- ERROR_REPORT2(IXGBE_ERROR_CAUTION,
- "Unable to initialize CS4227, err=%d\n", status);
+
+ /* Reset the CS4227. */
+ status = ixgbe_reset_cs4227(hw);
+ if (status != IXGBE_SUCCESS) {
+ ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+ "CS4227 reset failed: %d", status);
+ goto out;
+ }
+
+ /* Reset takes so long, temporarily release semaphore in case the
+ * other driver instance is waiting for the reset indication.
+ */
+ ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
+ IXGBE_CS4227_RESET_PENDING);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msec_delay(10);
+ status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+ if (status != IXGBE_SUCCESS) {
+ ERROR_REPORT2(IXGBE_ERROR_CAUTION,
+ "semaphore failed with %d", status);
+ return;
+ }
+
+ /* Record completion for next time. */
+ status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
+ IXGBE_CS4227_RESET_COMPLETE);
+
+out:
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msec_delay(hw->eeprom.semaphore_delay);
}
/**
@@ -452,8 +411,11 @@ s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
hw->bus.type = ixgbe_bus_type_internal;
mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
- mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
- mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
+ if (hw->mac.type == ixgbe_mac_X550EM_x) {
+ mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
+ mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
+ }
+
mac->ops.get_media_type = ixgbe_get_media_type_X550em;
mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
@@ -679,7 +641,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
if (enable_eee) {
eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
- if (hw->device_id == IXGBE_DEV_ID_X550T) {
+ if (hw->mac.type == ixgbe_mac_X550) {
/* Advertise EEE capability */
hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg);
@@ -717,7 +679,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
} else {
eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
- if (hw->device_id == IXGBE_DEV_ID_X550T) {
+ if (hw->mac.type == ixgbe_mac_X550) {
/* Disable advertised EEE capability */
hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg);
@@ -816,7 +778,7 @@ void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
**/
static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl)
{
- u32 i, command;
+ u32 i, command = 0;
/* Check every 10 usec to see if the address cycle completed.
* The SB IOSF BUSY bit will clear when the operation is
@@ -1003,7 +965,7 @@ void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf)
num_qs = 4; /* 32 VFs / pools */
bitmask = 0x0000000F;
break;
- default: /* 64 VFs / pools */
+ default: /* 64 VFs / pools */
num_qs = 2;
bitmask = 0x00000003;
break;
@@ -1302,7 +1264,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
return status;
- /* High temperature failure alarm triggered */
+ /* Global alarm triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
&reg);
@@ -1315,6 +1277,21 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
/* power down the PHY in case the PHY FW didn't already */
ixgbe_set_copper_phy_power(hw, FALSE);
return IXGBE_ERR_OVERTEMP;
+ } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
+ /* device fault alarm triggered */
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ &reg);
+
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ /* if device fault was due to high temp alarm handle and exit */
+ if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
+ /* power down the PHY in case the PHY FW didn't */
+ ixgbe_set_copper_phy_power(hw, FALSE);
+ return IXGBE_ERR_OVERTEMP;
+ }
}
/* Vendor alarm 2 triggered */
@@ -1444,8 +1421,6 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
return status;
reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
- reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ |
- IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC);
reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
@@ -1492,14 +1467,10 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
* to determine internal PHY mode.
*/
phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
-
- /* If internal PHY mode is KR, then initialize KR link */
if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) {
speed = IXGBE_LINK_SPEED_10GB_FULL |
IXGBE_LINK_SPEED_1GB_FULL;
- ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
}
-
phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
}
@@ -1516,7 +1487,7 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
/* Set functions pointers based on phy type */
switch (hw->phy.type) {
case ixgbe_phy_x550em_kx4:
- phy->ops.setup_link = ixgbe_setup_kx4_x550em;
+ phy->ops.setup_link = NULL;
phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
break;
@@ -1543,7 +1514,11 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
}
- phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
+ /* setup SW LPLU only for first revision */
+ if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw,
+ IXGBE_FUSES0_GROUP(0))))
+ phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
+
phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
phy->ops.reset = ixgbe_reset_phy_t_X550em;
break;
@@ -1580,9 +1555,14 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
/* flush pending Tx transactions */
ixgbe_clear_tx_pending(hw);
- /* PHY ops must be identified and initialized prior to reset */
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+ /* Config MDIO clock speed before the first MDIO PHY access */
+ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+ }
- /* Identify PHY and related function pointers */
+ /* PHY ops must be identified and initialized prior to reset */
status = hw->phy.ops.init(hw);
if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
@@ -1659,13 +1639,6 @@ mac_reset_top:
hw->mac.num_rar_entries = 128;
hw->mac.ops.init_rx_addrs(hw);
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
- /* Config MDIO clock speed. */
- hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
- hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
- IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
- }
-
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
ixgbe_setup_mux_ctl(hw);
@@ -1727,43 +1700,6 @@ s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
}
/**
- * ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
- * @hw: pointer to hardware structure
- *
- * Configures the integrated KX4 PHY.
- **/
-s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw)
-{
- s32 status;
- u32 reg_val;
-
- status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1,
- IXGBE_SB_IOSF_TARGET_KX4_PCS, &reg_val);
- if (status)
- return status;
-
- reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 |
- IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX);
-
- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE;
-
- /* Advertise 10G support. */
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4;
-
- /* Advertise 1G support. */
- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX;
-
- /* Restart auto-negotiation. */
- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART;
- status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1,
- IXGBE_SB_IOSF_TARGET_KX4_PCS, reg_val);
-
- return status;
-}
-
-/**
* ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
* @hw: pointer to hardware structure
*
@@ -1791,38 +1727,53 @@ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
if (ret_val != IXGBE_SUCCESS)
return ret_val;
- /* Configure CS4227 for LINE connection rate then type. */
- reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
- reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
-
- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
- if (setup_linear)
- reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- else
- reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
-
- /* Configure CS4227 for HOST connection rate then type. */
- reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
- reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
-
- reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
- if (setup_linear)
- reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
- else
+ if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
+ /* Configure CS4227 LINE side to 10G SR. */
+ reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB +
+ (hw->bus.lan_id << 12);
+ reg_val = IXGBE_CS4227_SPEED_10G;
+ ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+ reg_val);
+
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
+ (hw->bus.lan_id << 12);
reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
- ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
- reg_val);
+ ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+ reg_val);
+
+ /* Configure CS4227 for HOST connection rate then type. */
+ reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB +
+ (hw->bus.lan_id << 12);
+ reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ?
+ IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
+ ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+ reg_val);
+
+ reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB +
+ (hw->bus.lan_id << 12);
+ if (setup_linear)
+ reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ else
+ reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+ ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+ reg_val);
- /* If internal link mode is XFI, then setup XFI internal link. */
- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))
+ /* Setup XFI internal link. */
ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
-
+ } else {
+ /* Configure internal PHY for KR/KX. */
+ ixgbe_setup_kr_speed_x550em(hw, speed);
+
+ /* Configure CS4227 LINE side to proper mode. */
+ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
+ (hw->bus.lan_id << 12);
+ if (setup_linear)
+ reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+ else
+ reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+ ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+ reg_val);
+ }
return ret_val;
}
@@ -2743,6 +2694,10 @@ s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
u32 save_autoneg;
bool link_up;
+ /* SW LPLU not required on later HW revisions. */
+ if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))
+ return IXGBE_SUCCESS;
+
/* If blocked by MNG FW, then don't restart AN */
if (ixgbe_check_reset_blocked(hw))
return IXGBE_SUCCESS;
@@ -2924,7 +2879,7 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw)
goto out;
}
- if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
ret_val = ixgbe_read_iosf_sb_reg_x550(hw,
IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
@@ -2940,9 +2895,8 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw)
IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
- /* Not all devices fully support AN. */
- if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR)
- hw->fc.disable_fc_autoneg = TRUE;
+ /* This device does not fully support AN. */
+ hw->fc.disable_fc_autoneg = TRUE;
}
out:
diff --git a/sys/dev/ixgbe/ixgbe_x550.h b/sys/dev/ixgbe/ixgbe_x550.h
index 8a544ec..b590bb7 100644
--- a/sys/dev/ixgbe/ixgbe_x550.h
+++ b/sys/dev/ixgbe/ixgbe_x550.h
@@ -69,7 +69,7 @@ void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u32 data);
s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
- u32 device_type, u32 *data);
+ u32 device_type, u32 *data);
void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw);
void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw);
void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap);
@@ -82,7 +82,6 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw);
s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw);
s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw);
s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw);
-s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw);
s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw);
s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw);
s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw);
diff --git a/sys/dev/random/live_entropy_sources.c b/sys/dev/random/live_entropy_sources.c
index d406ebd..d25201a 100644
--- a/sys/dev/random/live_entropy_sources.c
+++ b/sys/dev/random/live_entropy_sources.c
@@ -189,7 +189,7 @@ live_entropy_sources_deinit(void *unused)
sx_destroy(&les_lock);
}
-SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+SYSINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST,
live_entropy_sources_init, NULL);
-SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+SYSUNINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST,
live_entropy_sources_deinit, NULL);
diff --git a/sys/dev/random/live_entropy_sources.h b/sys/dev/random/live_entropy_sources.h
index 9a23070..a1eec3e 100644
--- a/sys/dev/random/live_entropy_sources.h
+++ b/sys/dev/random/live_entropy_sources.h
@@ -52,7 +52,7 @@ void live_entropy_sources_feed(int, event_proc_f);
modevent, \
0 \
}; \
- DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \
+ DECLARE_MODULE(name, name##_mod, SI_SUB_RANDOM, \
SI_ORDER_SECOND); \
MODULE_VERSION(name, ver); \
MODULE_DEPEND(name, random, 1, 1, 1);
diff --git a/sys/dev/random/random_adaptors.c b/sys/dev/random/random_adaptors.c
index 4f5ad2c..d17abf7 100644
--- a/sys/dev/random/random_adaptors.c
+++ b/sys/dev/random/random_adaptors.c
@@ -233,9 +233,9 @@ random_adaptors_init(void *unused)
SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator");
-SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, random_adaptors_init,
+SYSINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST, random_adaptors_init,
NULL);
-SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+SYSUNINIT(random_adaptors, SI_SUB_RANDOM, SI_ORDER_FIRST,
random_adaptors_deinit, NULL);
static void
diff --git a/sys/dev/random/random_adaptors.h b/sys/dev/random/random_adaptors.h
index 4765694..b878b28 100644
--- a/sys/dev/random/random_adaptors.h
+++ b/sys/dev/random/random_adaptors.h
@@ -47,7 +47,7 @@ extern struct random_adaptor *random_adaptor;
/*
* random_adaptor's should be registered prior to
- * random module (SI_SUB_DRIVERS/SI_ORDER_MIDDLE)
+ * random module (SI_SUB_RANDOM/SI_ORDER_MIDDLE)
*/
#define RANDOM_ADAPTOR_MODULE(name, modevent, ver) \
static moduledata_t name##_mod = { \
@@ -55,7 +55,7 @@ extern struct random_adaptor *random_adaptor;
modevent, \
0 \
}; \
- DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \
+ DECLARE_MODULE(name, name##_mod, SI_SUB_RANDOM, \
SI_ORDER_SECOND); \
MODULE_VERSION(name, ver); \
MODULE_DEPEND(name, random, 1, 1, 1);
diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
index b7b8381..2638ea3 100644
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -81,6 +81,8 @@ int random_kthread_control = 0;
static struct proc *random_kthread_proc;
+static event_proc_f random_cb;
+
#ifdef RANDOM_RWFILE
static const char *entropy_files[] = {
"/entropy",
@@ -219,7 +221,7 @@ random_kthread(void *arg)
void
random_harvestq_init(event_proc_f cb)
{
- int error, i;
+ int i;
struct harvest *np;
/* Initialise the harvest fifos */
@@ -238,13 +240,26 @@ random_harvestq_init(event_proc_f cb)
mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN);
+ random_cb = cb;
+}
+
+static void
+random_harvestq_start_kproc(void *arg __unused)
+{
+ int error;
+
+ if (random_cb == NULL)
+ return;
+
/* Start the hash/reseed thread */
- error = kproc_create(random_kthread, cb,
+ error = kproc_create(random_kthread, random_cb,
&random_kthread_proc, RFHIGHPID, 0, "rand_harvestq"); /* RANDOM_CSPRNG_NAME */
if (error != 0)
panic("Cannot create entropy maintenance thread.");
}
+SYSINIT(random_kthread, SI_SUB_DRIVERS, SI_ORDER_ANY,
+ random_harvestq_start_kproc, NULL);
void
random_harvestq_deinit(void)
@@ -265,6 +280,17 @@ random_harvestq_deinit(void)
}
harvestfifo.count = 0;
+ /*
+ * Command the hash/reseed thread to end and wait for it to finish
+ */
+ mtx_lock_spin(&harvest_mtx);
+ if (random_kthread_proc != NULL) {
+ random_kthread_control = -1;
+ msleep_spin((void *)&random_kthread_control, &harvest_mtx,
+ "term", 0);
+ }
+ mtx_unlock_spin(&harvest_mtx);
+
mtx_destroy(&harvest_mtx);
}
diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c
index b76cb83..a220e7f 100644
--- a/sys/dev/random/randomdev.c
+++ b/sys/dev/random/randomdev.c
@@ -175,15 +175,24 @@ random_initialize(void *p, struct random_adaptor *s)
printf("random: <%s> initialized\n", s->ident);
+ /* mark random(4) as initialized, to avoid being called again */
+ random_inited = 1;
+}
+
+static void
+random_makedev(void *arg __unused)
+{
+
+ if (random_adaptor == NULL)
+ return;
+
/* Use an appropriately evil mode for those who are concerned
* with daemons */
random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw,
RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0666, "random");
make_dev_alias(random_dev, "urandom"); /* compatibility */
-
- /* mark random(4) as initialized, to avoid being called again */
- random_inited = 1;
}
+SYSINIT(random_makedev, SI_SUB_DRIVERS, SI_ORDER_ANY, random_makedev, NULL);
/* ARGSUSED */
static int
@@ -229,5 +238,11 @@ random_modevent(module_t mod __unused, int type, void *data __unused)
return (error);
}
-DEV_MODULE(random, random_modevent, NULL);
+static moduledata_t random_mod = {
+ "random",
+ random_modevent,
+ NULL
+};
+
+DECLARE_MODULE(random, random_mod, SI_SUB_RANDOM, SI_ORDER_MIDDLE);
MODULE_VERSION(random, 1);
diff --git a/sys/dev/random/randomdev_soft.c b/sys/dev/random/randomdev_soft.c
index 0929704..6badecc 100644
--- a/sys/dev/random/randomdev_soft.c
+++ b/sys/dev/random/randomdev_soft.c
@@ -182,12 +182,6 @@ randomdev_deinit(void)
/* Deregister the randomness harvesting routine */
randomdev_deinit_harvester();
- /*
- * Command the hash/reseed thread to end and wait for it to finish
- */
- random_kthread_control = -1;
- tsleep((void *)&random_kthread_control, 0, "term", 0);
-
#if defined(RANDOM_YARROW)
random_yarrow_deinit_alg();
#endif
diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h
index ce70546..14374cf 100644
--- a/sys/dev/sfxge/common/efx.h
+++ b/sys/dev/sfxge/common/efx.h
@@ -879,6 +879,14 @@ efx_phy_media_type_get(
__in efx_nic_t *enp,
__out efx_phy_media_type_t *typep);
+extern efx_rc_t
+efx_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data);
+
#if EFSYS_OPT_PHY_STATS
/* START MKCONFIG GENERATED PhyHeaderStatsBlock 30ed56ad501f8e36 */
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c
index 9f7a9ff..bb9d9cf 100644
--- a/sys/dev/sfxge/common/efx_mcdi.c
+++ b/sys/dev/sfxge/common/efx_mcdi.c
@@ -2078,5 +2078,217 @@ fail1:
return (rc);
}
+/*
+ * Size of media information page in accordance with SFF-8472 and SFF-8436.
+ * It is used in MCDI interface as well.
+ */
+#define EFX_PHY_MEDIA_INFO_PAGE_SIZE 0x80
+
+static __checkReturn efx_rc_t
+efx_mcdi_get_phy_media_info(
+ __in efx_nic_t *enp,
+ __in uint32_t mcdi_page,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN,
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(
+ EFX_PHY_MEDIA_INFO_PAGE_SIZE))];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT((uint32_t)offset + len <= EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_GET_PHY_MEDIA_INFO;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length =
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+
+ MCDI_IN_SET_DWORD(req, GET_PHY_MEDIA_INFO_IN_PAGE, mcdi_page);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used !=
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE)) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ if (MCDI_OUT_DWORD(req, GET_PHY_MEDIA_INFO_OUT_DATALEN) !=
+ EFX_PHY_MEDIA_INFO_PAGE_SIZE) {
+ rc = EIO;
+ goto fail3;
+ }
+
+ memcpy(data,
+ MCDI_OUT2(req, uint8_t, GET_PHY_MEDIA_INFO_OUT_DATA) + offset,
+ len);
+
+ return (0);
+
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+/*
+ * 2-wire device address of the base information in accordance with SFF-8472
+ * Diagnostic Monitoring Interface for Optical Transceivers section
+ * 4 Memory Organization.
+ */
+#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE 0xA0
+
+/*
+ * 2-wire device address of the digital diagnostics monitoring interface
+ * in accordance with SFF-8472 Diagnostic Monitoring Interface for Optical
+ * Transceivers section 4 Memory Organization.
+ */
+#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM 0xA2
+
+/*
+ * Hard wired 2-wire device address for QSFP+ in accordance with SFF-8436
+ * QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER section 7.4 Device Addressing and
+ * Operation.
+ */
+#define EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP 0xA0
+
+ __checkReturn efx_rc_t
+efx_mcdi_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data)
+{
+ efx_port_t *epp = &(enp->en_port);
+ efx_rc_t rc;
+ uint32_t mcdi_lower_page;
+ uint32_t mcdi_upper_page;
+
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+
+ /*
+ * Map device address to MC_CMD_GET_PHY_MEDIA_INFO pages.
+ * Offset plus length interface allows to access page 0 only.
+ * I.e. non-zero upper pages are not accessible.
+ * See SFF-8472 section 4 Memory Organization and SFF-8436 section 7.6
+ * QSFP+ Memory Map for details on how information is structured
+ * and accessible.
+ */
+ switch (epp->ep_fixed_port_type) {
+ case EFX_PHY_MEDIA_SFP_PLUS:
+ /*
+ * In accordance with SFF-8472 Diagnostic Monitoring
+ * Interface for Optical Transceivers section 4 Memory
+ * Organization two 2-wire addresses are defined.
+ */
+ switch (dev_addr) {
+ /* Base information */
+ case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE:
+ /*
+ * MCDI page 0 should be used to access lower
+ * page 0 (0x00 - 0x7f) at the device address 0xA0.
+ */
+ mcdi_lower_page = 0;
+ /*
+ * MCDI page 1 should be used to access upper
+ * page 0 (0x80 - 0xff) at the device address 0xA0.
+ */
+ mcdi_upper_page = 1;
+ break;
+ /* Diagnostics */
+ case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM:
+ /*
+ * MCDI page 2 should be used to access lower
+ * page 0 (0x00 - 0x7f) at the device address 0xA2.
+ */
+ mcdi_lower_page = 2;
+ /*
+ * MCDI page 3 should be used to access upper
+ * page 0 (0x80 - 0xff) at the device address 0xA2.
+ */
+ mcdi_upper_page = 3;
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail1;
+ }
+ break;
+ case EFX_PHY_MEDIA_QSFP_PLUS:
+ switch (dev_addr) {
+ case EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP:
+ /*
+ * MCDI page -1 should be used to access lower page 0
+ * (0x00 - 0x7f).
+ */
+ mcdi_lower_page = (uint32_t)-1;
+ /*
+ * MCDI page 0 should be used to access upper page 0
+ * (0x80h - 0xff).
+ */
+ mcdi_upper_page = 0;
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail1;
+ }
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ if (offset < EFX_PHY_MEDIA_INFO_PAGE_SIZE) {
+ uint8_t read_len =
+ MIN(len, EFX_PHY_MEDIA_INFO_PAGE_SIZE - offset);
+
+ rc = efx_mcdi_get_phy_media_info(enp,
+ mcdi_lower_page, offset, read_len, data);
+ if (rc != 0)
+ goto fail2;
+
+ data += read_len;
+ len -= read_len;
+
+ offset = 0;
+ } else {
+ offset -= EFX_PHY_MEDIA_INFO_PAGE_SIZE;
+ }
+
+ if (len > 0) {
+ EFSYS_ASSERT3U(len, <=, EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+ EFSYS_ASSERT3U(offset, <, EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+
+ rc = efx_mcdi_get_phy_media_info(enp,
+ mcdi_upper_page, offset, len, data);
+ if (rc != 0)
+ goto fail3;
+ }
+
+ return (0);
+
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
#endif /* EFSYS_OPT_MCDI */
diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h
index dd1d76e..a96bd77 100644
--- a/sys/dev/sfxge/common/efx_mcdi.h
+++ b/sys/dev/sfxge/common/efx_mcdi.h
@@ -228,6 +228,14 @@ efx_mcdi_get_loopback_modes(
__in efx_nic_t *enp);
#endif /* EFSYS_OPT_LOOPBACK */
+extern __checkReturn efx_rc_t
+efx_mcdi_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data);
+
#define MCDI_IN(_emr, _type, _ofst) \
((_type *)((_emr).emr_in_buf + (_ofst)))
diff --git a/sys/dev/sfxge/common/efx_phy.c b/sys/dev/sfxge/common/efx_phy.c
index 51e1ccb..3fd4e08 100644
--- a/sys/dev/sfxge/common/efx_phy.c
+++ b/sys/dev/sfxge/common/efx_phy.c
@@ -560,6 +560,38 @@ efx_phy_media_type_get(
*typep = epp->ep_fixed_port_type;
}
+ __checkReturn efx_rc_t
+efx_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data)
+{
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT(data != NULL);
+
+ if ((uint32_t)offset + len > 0xff) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
+ offset, len, data)) != 0)
+ goto fail2;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
#if EFSYS_OPT_PHY_STATS
#if EFSYS_OPT_NAMES
diff --git a/sys/dev/sfxge/sfxge.c b/sys/dev/sfxge/sfxge.c
index b82fba4..b112a1e 100644
--- a/sys/dev/sfxge/sfxge.c
+++ b/sys/dev/sfxge/sfxge.c
@@ -507,6 +507,30 @@ sfxge_if_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
break;
+#ifdef SIOCGI2C
+ case SIOCGI2C:
+ {
+ struct ifi2creq i2c;
+
+ error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
+ if (error != 0)
+ break;
+
+ if (i2c.len > sizeof(i2c.data)) {
+ error = EINVAL;
+ break;
+ }
+
+ SFXGE_ADAPTER_LOCK(sc);
+ error = efx_phy_module_get_info(sc->enp, i2c.dev_addr,
+ i2c.offset, i2c.len,
+ &i2c.data[0]);
+ SFXGE_ADAPTER_UNLOCK(sc);
+ if (error == 0)
+ error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
+ break;
+ }
+#endif
case SIOCGPRIVATE_0:
error = priv_check(curthread, PRIV_DRIVER);
if (error != 0)
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 394d61f..e3c08de 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1709,7 +1709,8 @@ static void
__elfN(putnote)(struct note_info *ninfo, struct sbuf *sb)
{
Elf_Note note;
- ssize_t old_len;
+ ssize_t old_len, sect_len;
+ size_t new_len, descsz, i;
if (ninfo->type == -1) {
ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize);
@@ -1728,7 +1729,33 @@ __elfN(putnote)(struct note_info *ninfo, struct sbuf *sb)
return;
sbuf_start_section(sb, &old_len);
ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize);
- sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0);
+ sect_len = sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0);
+ if (sect_len < 0)
+ return;
+
+ new_len = (size_t)sect_len;
+ descsz = roundup(note.n_descsz, ELF_NOTE_ROUNDSIZE);
+ if (new_len < descsz) {
+ /*
+ * It is expected that individual note emitters will correctly
+ * predict their expected output size and fill up to that size
+ * themselves, padding in a format-specific way if needed.
+ * However, in case they don't, just do it here with zeros.
+ */
+ for (i = 0; i < descsz - new_len; i++)
+ sbuf_putc(sb, 0);
+ } else if (new_len > descsz) {
+ /*
+ * We can't always truncate sb -- we may have drained some
+ * of it already.
+ */
+ KASSERT(new_len == descsz, ("%s: Note type %u changed as we "
+ "read it (%zu > %zu). Since it is longer than "
+ "expected, this coredump's notes are corrupt. THIS "
+ "IS A BUG in the note_procstat routine for type %u.\n",
+ __func__, (unsigned)note.n_type, new_len, descsz,
+ (unsigned)note.n_type));
+ }
}
/*
@@ -1909,25 +1936,47 @@ static void
note_procstat_files(void *arg, struct sbuf *sb, size_t *sizep)
{
struct proc *p;
- size_t size;
- int structsize;
+ size_t size, sect_sz, i;
+ ssize_t start_len, sect_len;
+ int structsize, filedesc_flags;
+
+ if (coredump_pack_fileinfo)
+ filedesc_flags = KERN_FILEDESC_PACK_KINFO;
+ else
+ filedesc_flags = 0;
p = (struct proc *)arg;
+ structsize = sizeof(struct kinfo_file);
if (sb == NULL) {
size = 0;
sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
sbuf_set_drain(sb, sbuf_drain_count, &size);
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_filedesc_out(p, sb, -1);
+ kern_proc_filedesc_out(p, sb, -1, filedesc_flags);
sbuf_finish(sb);
sbuf_delete(sb);
*sizep = size;
} else {
- structsize = sizeof(struct kinfo_file);
+ sbuf_start_section(sb, &start_len);
+
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_filedesc_out(p, sb, -1);
+ kern_proc_filedesc_out(p, sb, *sizep - sizeof(structsize),
+ filedesc_flags);
+
+ sect_len = sbuf_end_section(sb, start_len, 0, 0);
+ if (sect_len < 0)
+ return;
+ sect_sz = sect_len;
+
+ KASSERT(sect_sz <= *sizep,
+ ("kern_proc_filedesc_out did not respect maxlen; "
+ "requested %zu, got %zu", *sizep - sizeof(structsize),
+ sect_sz - sizeof(structsize)));
+
+ for (i = 0; i < *sizep - sect_sz && sb->s_error == 0; i++)
+ sbuf_putc(sb, 0);
}
}
@@ -1940,24 +1989,30 @@ note_procstat_vmmap(void *arg, struct sbuf *sb, size_t *sizep)
{
struct proc *p;
size_t size;
- int structsize;
+ int structsize, vmmap_flags;
+
+ if (coredump_pack_vmmapinfo)
+ vmmap_flags = KERN_VMMAP_PACK_KINFO;
+ else
+ vmmap_flags = 0;
p = (struct proc *)arg;
+ structsize = sizeof(struct kinfo_vmentry);
if (sb == NULL) {
size = 0;
sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
sbuf_set_drain(sb, sbuf_drain_count, &size);
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_vmmap_out(p, sb);
+ kern_proc_vmmap_out(p, sb, -1, vmmap_flags);
sbuf_finish(sb);
sbuf_delete(sb);
*sizep = size;
} else {
- structsize = sizeof(struct kinfo_vmentry);
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_vmmap_out(p, sb);
+ kern_proc_vmmap_out(p, sb, *sizep - sizeof(structsize),
+ vmmap_flags);
}
}
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 4930e2f..7561368 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/conf.h>
#include <sys/domain.h>
+#include <sys/fail.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
@@ -3299,6 +3300,7 @@ struct export_fd_buf {
struct sbuf *sb;
ssize_t remainder;
struct kinfo_file kif;
+ int flags;
};
static int
@@ -3385,9 +3387,12 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
kif->kf_type = type;
kif->kf_ref_count = refcnt;
kif->kf_offset = offset;
- /* Pack record size down */
- kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
- strlen(kif->kf_path) + 1;
+ if ((efbuf->flags & KERN_FILEDESC_PACK_KINFO) != 0)
+ /* Pack record size down */
+ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
+ strlen(kif->kf_path) + 1;
+ else
+ kif->kf_structsize = sizeof(*kif);
kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
if (efbuf->remainder != -1) {
if (efbuf->remainder < kif->kf_structsize) {
@@ -3413,7 +3418,8 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
* Takes a locked proc as argument, and returns with the proc unlocked.
*/
int
-kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
+kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
+ int flags)
{
struct file *fp;
struct filedesc *fdp;
@@ -3448,6 +3454,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
efbuf->fdp = NULL;
efbuf->sb = sb;
efbuf->remainder = maxlen;
+ efbuf->flags = flags;
if (tracevp != NULL)
export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
FREAD | FWRITE, -1, -1, NULL, efbuf);
@@ -3597,7 +3604,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
return (error);
}
maxlen = req->oldptr != NULL ? req->oldlen : -1;
- error = kern_proc_filedesc_out(p, &sb, maxlen);
+ error = kern_proc_filedesc_out(p, &sb, maxlen,
+ KERN_FILEDESC_PACK_KINFO);
error2 = sbuf_finish(&sb);
sbuf_delete(&sb);
return (error != 0 ? error : error2);
@@ -3635,6 +3643,24 @@ vntype_to_kinfo(int vtype)
return (KF_VTYPE_UNKNOWN);
}
+static inline void
+vn_fill_junk(struct kinfo_file *kif)
+{
+ size_t len, olen;
+
+ /*
+ * Simulate vn_fullpath returning changing values for a given
+ * vp during e.g. coredump.
+ */
+ len = (arc4random() % (sizeof(kif->kf_path) - 2)) + 1;
+ olen = strlen(kif->kf_path);
+ if (len < olen)
+ strcpy(&kif->kf_path[len - 1], "$");
+ else
+ for (; olen < len; olen++)
+ strcpy(&kif->kf_path[olen], "A");
+}
+
static int
fill_vnode_info(struct vnode *vp, struct kinfo_file *kif)
{
@@ -3654,6 +3680,10 @@ fill_vnode_info(struct vnode *vp, struct kinfo_file *kif)
if (freepath != NULL)
free(freepath, M_TEMP);
+ KFAIL_POINT_CODE(DEBUG_FP, fill_kinfo_vnode__random_path,
+ vn_fill_junk(kif);
+ );
+
/*
* Retrieve vnode attributes.
*/
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index f82ffec..47ea9b0 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -102,6 +102,16 @@ SDT_PROBE_DEFINE1(proc, kernel, , exec__success, "char *");
MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
+int coredump_pack_fileinfo = 1;
+SYSCTL_INT(_kern, OID_AUTO, coredump_pack_fileinfo, CTLFLAG_RWTUN,
+ &coredump_pack_fileinfo, 0,
+ "Enable file path packing in 'procstat -f' coredump notes");
+
+int coredump_pack_vmmapinfo = 1;
+SYSCTL_INT(_kern, OID_AUTO, coredump_pack_vmmapinfo, CTLFLAG_RWTUN,
+ &coredump_pack_vmmapinfo, 0,
+ "Enable file path packing in 'procstat -v' coredump notes");
+
static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS);
static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS);
static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 6b60840..cfaa354 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -2228,7 +2228,7 @@ next:;
* Must be called with the process locked and will return unlocked.
*/
int
-kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
+kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags)
{
vm_map_entry_t entry, tmp_entry;
struct vattr va;
@@ -2252,7 +2252,7 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
PRELE(p);
return (ESRCH);
}
- kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK);
+ kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK | M_ZERO);
error = 0;
map = &vm->vm_map;
@@ -2387,10 +2387,23 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
free(freepath, M_TEMP);
/* Pack record size down */
- kve->kve_structsize = offsetof(struct kinfo_vmentry, kve_path) +
- strlen(kve->kve_path) + 1;
+ if ((flags & KERN_VMMAP_PACK_KINFO) != 0)
+ kve->kve_structsize =
+ offsetof(struct kinfo_vmentry, kve_path) +
+ strlen(kve->kve_path) + 1;
+ else
+ kve->kve_structsize = sizeof(*kve);
kve->kve_structsize = roundup(kve->kve_structsize,
sizeof(uint64_t));
+
+ /* Halt filling and truncate rather than exceeding maxlen */
+ if (maxlen != -1 && maxlen < kve->kve_structsize) {
+ error = 0;
+ vm_map_lock_read(map);
+ break;
+ } else if (maxlen != -1)
+ maxlen -= kve->kve_structsize;
+
if (sbuf_bcat(sb, kve, kve->kve_structsize) != 0)
error = ENOMEM;
vm_map_lock_read(map);
@@ -2422,7 +2435,7 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS)
sbuf_delete(&sb);
return (error);
}
- error = kern_proc_vmmap_out(p, &sb);
+ error = kern_proc_vmmap_out(p, &sb, -1, KERN_VMMAP_PACK_KINFO);
error2 = sbuf_finish(&sb);
sbuf_delete(&sb);
return (error != 0 ? error : error2);
diff --git a/sys/modules/ix/Makefile b/sys/modules/ix/Makefile
index 4b57379..2d567e4 100644
--- a/sys/modules/ix/Makefile
+++ b/sys/modules/ix/Makefile
@@ -5,7 +5,7 @@
KMOD = if_ix
SRCS = device_if.h bus_if.h pci_if.h
SRCS += opt_inet.h opt_inet6.h
-SRCS += if_ix.c ix_txrx.c
+SRCS += if_ix.c ix_txrx.c ixgbe_osdep.c
# Shared source
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c
SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c
diff --git a/sys/modules/ixv/Makefile b/sys/modules/ixv/Makefile
index fd428a0..9546a3c 100644
--- a/sys/modules/ixv/Makefile
+++ b/sys/modules/ixv/Makefile
@@ -5,7 +5,7 @@
KMOD = if_ixv
SRCS = device_if.h bus_if.h pci_if.h
SRCS += opt_inet.h opt_inet6.h
-SRCS += if_ixv.c ix_txrx.c
+SRCS += if_ixv.c ix_txrx.c ixgbe_osdep.c
# Shared source
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_mbx.c ixgbe_vf.c
SRCS += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c
diff --git a/sys/sys/exec.h b/sys/sys/exec.h
index cccebfd..0ccba24 100644
--- a/sys/sys/exec.h
+++ b/sys/sys/exec.h
@@ -83,6 +83,9 @@ void exec_unmap_first_page(struct image_params *);
int exec_register(const struct execsw *);
int exec_unregister(const struct execsw *);
+extern int coredump_pack_fileinfo;
+extern int coredump_pack_vmmapinfo;
+
/*
* note: name##_mod cannot be const storage because the
* linker_file_sysinit() function modifies _file in the
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 9374daf..a697b66 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -536,6 +536,11 @@ struct kinfo_sigtramp {
#define KERN_PROC_NOTHREADS 0x1
#define KERN_PROC_MASK32 0x2
+/* Flags for kern_proc_filedesc_out. */
+#define KERN_FILEDESC_PACK_KINFO 0x00000001U
+
+/* Flags for kern_proc_vmmap_out. */
+#define KERN_VMMAP_PACK_KINFO 0x00000001U
struct sbuf;
/*
@@ -547,9 +552,11 @@ struct sbuf;
* to be locked on enter. On return the process is unlocked.
*/
-int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen);
+int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
+ int flags);
int kern_proc_out(struct proc *p, struct sbuf *sb, int flags);
-int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb);
+int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
+ int flags);
int vntype_to_kinfo(int vtype);
#endif /* !_KERNEL */
diff --git a/usr.sbin/devctl/devctl.8 b/usr.sbin/devctl/devctl.8
index add170d..598bea1 100644
--- a/usr.sbin/devctl/devctl.8
+++ b/usr.sbin/devctl/devctl.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 5, 2015
+.Dd February 2, 2016
.Dt DEVCTL 8
.Os
.Sh NAME
@@ -123,4 +123,4 @@ the device will not be changed.
The
.Nm
utility first appeared in
-.Fx 11.0 .
+.Fx 10.3 .
OpenPOWER on IntegriCloud