Merge branch 'stable-1.5' into soe-handler
This commit is contained in:
commit
6c6b68c00b
|
|
@ -43,3 +43,6 @@ script/ethercatctl
|
||||||
script/init.d/ethercat
|
script/init.d/ethercat
|
||||||
stamp-h1
|
stamp-h1
|
||||||
tool/ethercat
|
tool/ethercat
|
||||||
|
device_drivers.md
|
||||||
|
generated_table.md
|
||||||
|
doxygen-output/
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
image:
|
image:
|
||||||
registry.gitlab.com/etherlab.org/build-container-factory/leap-15.3:linux-syms
|
registry.gitlab.com/etherlab.org/build-container-factory/leap-15.3:linux-syms
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- doc
|
||||||
|
- deploy
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
|
||||||
|
|
@ -43,13 +49,13 @@ test cmake:
|
||||||
# It must be named 'doxygen' and must produce an artifact with a 'html'
|
# It must be named 'doxygen' and must produce an artifact with a 'html'
|
||||||
# directory directly containing the doxygen index HTML.
|
# directory directly containing the doxygen index HTML.
|
||||||
doxygen:
|
doxygen:
|
||||||
stage: deploy
|
stage: doc
|
||||||
variables:
|
variables:
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
script:
|
script:
|
||||||
- ./bootstrap
|
- ./bootstrap
|
||||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat
|
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat
|
||||||
- doxygen
|
- make doc
|
||||||
- mv doxygen-output/html/ html/
|
- mv doxygen-output/html/ html/
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
|
|
@ -59,7 +65,7 @@ doxygen:
|
||||||
# It must be named 'pdf' and must produce a 'pdf' directory as an artifact.
|
# It must be named 'pdf' and must produce a 'pdf' directory as an artifact.
|
||||||
# All PDF files in this directory will be collected.
|
# All PDF files in this directory will be collected.
|
||||||
pdf:
|
pdf:
|
||||||
stage: deploy
|
stage: doc
|
||||||
image: registry.gitlab.com/etherlab.org/build-container-factory/leap-15.3:texlive
|
image: registry.gitlab.com/etherlab.org/build-container-factory/leap-15.3:texlive
|
||||||
script:
|
script:
|
||||||
- cd documentation
|
- cd documentation
|
||||||
|
|
@ -73,6 +79,13 @@ pdf:
|
||||||
paths:
|
paths:
|
||||||
- pdf/
|
- pdf/
|
||||||
|
|
||||||
|
# Trigger EtherLab Documentation project to update https://docs.etherlab.org
|
||||||
|
update docs server:
|
||||||
|
stage: deploy
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == "stable-1.5" && $CI_PROJECT_NAMESPACE == "etherlab.org"
|
||||||
|
trigger: etherlab.org/docs
|
||||||
|
|
||||||
# from 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml', but on all branches
|
# from 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml', but on all branches
|
||||||
workflow:
|
workflow:
|
||||||
rules:
|
rules:
|
||||||
|
|
|
||||||
17
Doxyfile.in
17
Doxyfile.in
|
|
@ -45,7 +45,7 @@ PROJECT_BRIEF =
|
||||||
# exceed 55 pixels and the maximum width should not exceed 200 pixels.
|
# exceed 55 pixels and the maximum width should not exceed 200 pixels.
|
||||||
# Doxygen will copy the logo to the output directory.
|
# Doxygen will copy the logo to the output directory.
|
||||||
|
|
||||||
PROJECT_LOGO = doxygen-layout/images/igh+logo.svg
|
PROJECT_LOGO = @top_srcdir@/doxygen-layout/images/igh+logo.svg
|
||||||
|
|
||||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||||
# base path where the generated documentation will be put.
|
# base path where the generated documentation will be put.
|
||||||
|
|
@ -655,9 +655,10 @@ WARN_LOGFILE =
|
||||||
# directories like "/usr/src/myproject". Separate the files or directories
|
# directories like "/usr/src/myproject". Separate the files or directories
|
||||||
# with spaces.
|
# with spaces.
|
||||||
|
|
||||||
INPUT = master \
|
INPUT = @top_srcdir@/master \
|
||||||
include \
|
@top_srcdir@/include \
|
||||||
devices/ecdev.h
|
@top_srcdir@/devices/ecdev.h \
|
||||||
|
@top_builddir@/device_drivers.md
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||||
|
|
@ -886,13 +887,13 @@ HTML_FILE_EXTENSION = .html
|
||||||
# have to redo this when upgrading to a newer version of doxygen or when
|
# have to redo this when upgrading to a newer version of doxygen or when
|
||||||
# changing the value of configuration settings such as GENERATE_TREEVIEW!
|
# changing the value of configuration settings such as GENERATE_TREEVIEW!
|
||||||
|
|
||||||
HTML_HEADER = doxygen-layout/style/html_header.html
|
HTML_HEADER = @top_srcdir@/doxygen-layout/style/html_header.html
|
||||||
|
|
||||||
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
||||||
# each generated HTML page. If it is left blank doxygen will generate a
|
# each generated HTML page. If it is left blank doxygen will generate a
|
||||||
# standard footer.
|
# standard footer.
|
||||||
|
|
||||||
HTML_FOOTER = doxygen-layout/style/html_footer.html
|
HTML_FOOTER = @top_srcdir@/doxygen-layout/style/html_footer.html
|
||||||
|
|
||||||
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
|
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
|
||||||
# style sheet that is used by each HTML page. It can be used to
|
# style sheet that is used by each HTML page. It can be used to
|
||||||
|
|
@ -903,8 +904,8 @@ HTML_FOOTER = doxygen-layout/style/html_footer.html
|
||||||
|
|
||||||
HTML_STYLESHEET =
|
HTML_STYLESHEET =
|
||||||
|
|
||||||
HTML_EXTRA_STYLESHEET = doxygen-layout/style/custom.css \
|
HTML_EXTRA_STYLESHEET = @top_srcdir@/doxygen-layout/style/custom.css \
|
||||||
doxygen-layout/style/custom_igh_theme.css
|
@top_srcdir@/doxygen-layout/style/custom_igh_theme.css
|
||||||
|
|
||||||
|
|
||||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||||
|
|
|
||||||
10
Makefile.am
10
Makefile.am
|
|
@ -100,10 +100,16 @@ mrproper: clean cleandoc
|
||||||
libtool \
|
libtool \
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
|
||||||
doc:
|
generated_table.md: devices/create_driver_table.py
|
||||||
|
python3 $< --markdown $@ $(abs_srcdir)/devices
|
||||||
|
|
||||||
|
device_drivers.md: $(srcdir)/devices/device_drivers_template.md generated_table.md
|
||||||
|
cat $^ > $@
|
||||||
|
|
||||||
|
doc: device_drivers.md
|
||||||
doxygen Doxyfile
|
doxygen Doxyfile
|
||||||
|
|
||||||
cleandoc:
|
cleandoc:
|
||||||
@rm -rf doxygen-output
|
@rm -rf doxygen-output generated_table.md device_drivers.md
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ KBUILD = $(MAKE) -C "$(LINUX_SOURCE_DIR)" M="$(abs_srcdir)" INSTALL_MOD_DIR="$(I
|
||||||
|
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
$(KBUILD) modules
|
+$(KBUILD) modules
|
||||||
|
|
||||||
modules_install:
|
modules_install:
|
||||||
$(KBUILD) modules_install
|
+$(KBUILD) modules_install
|
||||||
|
|
||||||
|
|
||||||
# Override default `clean` target to call Kbuild clean *before* automake
|
# Override default `clean` target to call Kbuild clean *before* automake
|
||||||
|
|
|
||||||
98
configure.ac
98
configure.ac
|
|
@ -432,6 +432,54 @@ fi
|
||||||
AC_SUBST(KERNEL_E1000E,[$kernele1000e])
|
AC_SUBST(KERNEL_E1000E,[$kernele1000e])
|
||||||
AC_SUBST(E1000E_LAYOUT, [$e1000elayout])
|
AC_SUBST(E1000E_LAYOUT, [$e1000elayout])
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# genet driver
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([genet],
|
||||||
|
AS_HELP_STRING([--enable-genet],
|
||||||
|
[Enable genet driver (for Raspi 4)]),
|
||||||
|
[
|
||||||
|
case "${enableval}" in
|
||||||
|
yes) enablegenet=1
|
||||||
|
;;
|
||||||
|
no) enablegenet=0
|
||||||
|
;;
|
||||||
|
*) AC_MSG_ERROR([Invalid value for --enable-genet])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
],
|
||||||
|
[enablegenet=0] # disabled by default
|
||||||
|
)
|
||||||
|
|
||||||
|
AM_CONDITIONAL(ENABLE_GENET, test "x$enablegenet" = "x1")
|
||||||
|
AC_SUBST(ENABLE_GENET,[$enablegenet])
|
||||||
|
|
||||||
|
AC_ARG_WITH([genet-kernel],
|
||||||
|
AC_HELP_STRING(
|
||||||
|
[--with-genet-kernel=<X.Y.Z>],
|
||||||
|
[genet kernel (only if differing)]
|
||||||
|
),
|
||||||
|
[
|
||||||
|
kernelgenet=[$withval]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
kernelgenet=$linuxversion
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x${enablegenet}" = "x1"; then
|
||||||
|
AC_MSG_CHECKING([for kernel for genet driver])
|
||||||
|
|
||||||
|
if test ! -f "${srcdir}/devices/genet/bcmgenet-${kernelgenet}-orig.c"; then
|
||||||
|
AC_MSG_ERROR([kernel $kernelgenet not available for genet driver!])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_RESULT([$kernelgenet])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(KERNEL_GENET,[$kernelgenet])
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# igb driver
|
# igb driver
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
@ -479,6 +527,52 @@ if test "x${enableigb}" = "x1"; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(KERNEL_IGB,[$kerneligb])
|
AC_SUBST(KERNEL_IGB,[$kerneligb])
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# igc driver
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([igc],
|
||||||
|
AS_HELP_STRING([--enable-igc],
|
||||||
|
[Enable igc driver]),
|
||||||
|
[
|
||||||
|
case "${enableval}" in
|
||||||
|
yes) enableigc=1
|
||||||
|
;;
|
||||||
|
no) enableigc=0
|
||||||
|
;;
|
||||||
|
*) AC_MSG_ERROR([Invalid value for --enable-igc])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
],
|
||||||
|
[enableigc=0] # disabled by default
|
||||||
|
)
|
||||||
|
|
||||||
|
AM_CONDITIONAL(ENABLE_IGC, test "x$enableigc" = "x1")
|
||||||
|
AC_SUBST(ENABLE_IGC,[$enableigc])
|
||||||
|
|
||||||
|
AC_ARG_WITH([igc-kernel],
|
||||||
|
AS_HELP_STRING([--with-igc-kernel=<X.Y.Z>],
|
||||||
|
[igc kernel (only if differing)]
|
||||||
|
),
|
||||||
|
[
|
||||||
|
kerneligc=[$withval]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
kerneligc=$linuxversion
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x${enableigc}" = "x1"; then
|
||||||
|
AC_MSG_CHECKING([for kernel for igc driver])
|
||||||
|
|
||||||
|
if test ! -f "${srcdir}/devices/igc/igc_main-${kerneligc}-orig.c"; then
|
||||||
|
AC_MSG_ERROR([kernel $kerneligc not available for igc driver!])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_RESULT([$kerneligc])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(KERNEL_IGC,[$kerneligc])
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# r8169 driver
|
# r8169 driver
|
||||||
|
|
@ -1122,8 +1216,12 @@ AC_CONFIG_FILES([
|
||||||
devices/e1000/Makefile
|
devices/e1000/Makefile
|
||||||
devices/e1000e/Kbuild
|
devices/e1000e/Kbuild
|
||||||
devices/e1000e/Makefile
|
devices/e1000e/Makefile
|
||||||
|
devices/genet/Kbuild
|
||||||
|
devices/genet/Makefile
|
||||||
devices/igb/Kbuild
|
devices/igb/Kbuild
|
||||||
devices/igb/Makefile
|
devices/igb/Makefile
|
||||||
|
devices/igc/Kbuild
|
||||||
|
devices/igc/Makefile
|
||||||
ethercat.spec
|
ethercat.spec
|
||||||
examples/Kbuild
|
examples/Kbuild
|
||||||
examples/Makefile
|
examples/Makefile
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -70,10 +70,18 @@ ifeq (@ENABLE_E1000E@,1)
|
||||||
obj-m += e1000e/
|
obj-m += e1000e/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (@ENABLE_GENET@,1)
|
||||||
|
obj-m += genet/
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (@ENABLE_IGB@,1)
|
ifeq (@ENABLE_IGB@,1)
|
||||||
obj-m += igb/
|
obj-m += igb/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (@ENABLE_IGC@,1)
|
||||||
|
obj-m += igc/
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (@ENABLE_R8169@,1)
|
ifeq (@ENABLE_R8169@,1)
|
||||||
EC_R8169_OBJ := r8169-@KERNEL_R8169@-ethercat.o
|
EC_R8169_OBJ := r8169-@KERNEL_R8169@-ethercat.o
|
||||||
obj-m += ec_r8169.o
|
obj-m += ec_r8169.o
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# $Id$
|
# Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
|
||||||
#
|
|
||||||
# Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
|
|
||||||
#
|
#
|
||||||
# This file is part of the IgH EtherCAT Master.
|
# This file is part of the IgH EtherCAT Master.
|
||||||
#
|
#
|
||||||
|
|
@ -26,13 +24,16 @@
|
||||||
# industrial property and similar rights of Beckhoff Automation GmbH.
|
# industrial property and similar rights of Beckhoff Automation GmbH.
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.kbuild
|
include $(top_srcdir)/Makefile.kbuild
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
ccat \
|
ccat \
|
||||||
e1000 \
|
e1000 \
|
||||||
e1000e \
|
e1000e \
|
||||||
igb
|
genet \
|
||||||
|
igb \
|
||||||
|
igc
|
||||||
|
|
||||||
# using HEADERS to enable tags target
|
# using HEADERS to enable tags target
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
|
|
@ -94,6 +95,12 @@ noinst_HEADERS = \
|
||||||
8139too-3.8-orig.c \
|
8139too-3.8-orig.c \
|
||||||
8139too-4.4-ethercat.c \
|
8139too-4.4-ethercat.c \
|
||||||
8139too-4.4-orig.c \
|
8139too-4.4-orig.c \
|
||||||
|
8139too-5.10-ethercat.c \
|
||||||
|
8139too-5.10-orig.c \
|
||||||
|
8139too-6.1-ethercat.c \
|
||||||
|
8139too-6.1-orig.c \
|
||||||
|
create_driver_table.py \
|
||||||
|
device_drivers_template.md \
|
||||||
e100-2.6.20-ethercat.c \
|
e100-2.6.20-ethercat.c \
|
||||||
e100-2.6.20-orig.c \
|
e100-2.6.20-orig.c \
|
||||||
e100-2.6.24-ethercat.c \
|
e100-2.6.24-ethercat.c \
|
||||||
|
|
@ -134,6 +141,18 @@ noinst_HEADERS = \
|
||||||
e100-3.8-orig.c \
|
e100-3.8-orig.c \
|
||||||
e100-4.4-ethercat.c \
|
e100-4.4-ethercat.c \
|
||||||
e100-4.4-orig.c \
|
e100-4.4-orig.c \
|
||||||
|
e100-5.4-ethercat.c \
|
||||||
|
e100-5.4-orig.c \
|
||||||
|
e100-5.10-ethercat.c \
|
||||||
|
e100-5.10-orig.c \
|
||||||
|
e100-5.14-ethercat.c \
|
||||||
|
e100-5.14-orig.c \
|
||||||
|
e100-5.15-ethercat.c \
|
||||||
|
e100-5.15-orig.c \
|
||||||
|
e100-6.1-ethercat.c \
|
||||||
|
e100-6.1-orig.c \
|
||||||
|
e100-6.4-ethercat.c \
|
||||||
|
e100-6.4-orig.c \
|
||||||
ecdev.h \
|
ecdev.h \
|
||||||
generic.c \
|
generic.c \
|
||||||
r8169-2.6.24-ethercat.c \
|
r8169-2.6.24-ethercat.c \
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,11 @@ static int __init ccat_class_init(struct ccat_class *base)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
||||||
base->class = class_create(THIS_MODULE, base->name);
|
base->class = class_create(THIS_MODULE, base->name);
|
||||||
|
#else
|
||||||
|
base->class = class_create(base->name);
|
||||||
|
#endif
|
||||||
if (!base->class) {
|
if (!base->class) {
|
||||||
pr_warn("Create device class '%s' failed\n",
|
pr_warn("Create device class '%s' failed\n",
|
||||||
base->name);
|
base->name);
|
||||||
|
|
|
||||||
|
|
@ -249,9 +249,11 @@ struct ccat_mac_register {
|
||||||
u8 mii_connected;
|
u8 mii_connected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void ccat_eth_fifo_reset(struct ccat_eth_fifo *const fifo);
|
||||||
static void fifo_set_end(struct ccat_eth_fifo *const fifo, size_t size)
|
static void fifo_set_end(struct ccat_eth_fifo *const fifo, size_t size)
|
||||||
{
|
{
|
||||||
fifo->end = fifo->mem.start + size - sizeof(struct ccat_eth_frame);
|
fifo->end = fifo->mem.start + size - sizeof(struct ccat_eth_frame);
|
||||||
|
ccat_eth_fifo_reset(fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ccat_dma_free(struct ccat_eth_priv *const priv)
|
static void ccat_dma_free(struct ccat_eth_priv *const priv)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,165 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007-2023 Bjarne von Horn, Ingenieurgemeinschaft IgH
|
||||||
|
#
|
||||||
|
# This file is part of the IgH EtherCAT Master.
|
||||||
|
#
|
||||||
|
# The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License version 2, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
# Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with the IgH EtherCAT Master; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
# ---
|
||||||
|
#
|
||||||
|
# The license mentioned above concerns the source code only. Using the
|
||||||
|
# EtherCAT technology and brand is only permitted in compliance with the
|
||||||
|
# industrial property and similar rights of Beckhoff Automation GmbH.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
from os import walk
|
||||||
|
from os.path import join
|
||||||
|
from re import compile
|
||||||
|
|
||||||
|
DRIVER_MAP=(
|
||||||
|
# (subdir, driver name, file prefix)
|
||||||
|
(".", "8139too", "8139too"),
|
||||||
|
(".", "e100", "e100"),
|
||||||
|
("e1000", "e1000", "e1000_main"),
|
||||||
|
("e1000e", "e1000e", "netdev"),
|
||||||
|
("genet", "bcmgenet", "bcmgenet"),
|
||||||
|
("igb", "igb", "igb_main"),
|
||||||
|
("igc", "igc", "igc_main"),
|
||||||
|
(".", "r8169", "r8169"),
|
||||||
|
)
|
||||||
|
|
||||||
|
DRIVERS = tuple([x[1] for x in DRIVER_MAP])
|
||||||
|
|
||||||
|
def compile_regex(prefix, file_extension):
|
||||||
|
"""
|
||||||
|
:return: Compiled regex to extract Kernel version
|
||||||
|
"""
|
||||||
|
return compile("^" + prefix + "-([\d]+)\.([\d]+)-ethercat\."+file_extension+"$")
|
||||||
|
|
||||||
|
def filter_versions(file_list, prefix, file_extension):
|
||||||
|
"""
|
||||||
|
:return: Set of tuples with (major, minor) kernel versions.
|
||||||
|
"""
|
||||||
|
rex = compile_regex(prefix, file_extension)
|
||||||
|
ans = set()
|
||||||
|
for file in file_list:
|
||||||
|
match = rex.match(file)
|
||||||
|
if match is None:
|
||||||
|
continue
|
||||||
|
maj, min = match.group(1, 2)
|
||||||
|
ans.add((int(maj), int(min)))
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def get_all_drivers(drivers_dir):
|
||||||
|
"""
|
||||||
|
Walk through "devices" dir and collect all drivers.
|
||||||
|
|
||||||
|
:return: Dict with (major, minor) kernel version key and set of driver
|
||||||
|
names as values.
|
||||||
|
"""
|
||||||
|
files = next(walk(drivers_dir))[2]
|
||||||
|
driver_table = {}
|
||||||
|
def add_driver(versions, driver):
|
||||||
|
for version in versions:
|
||||||
|
if not version in driver_table:
|
||||||
|
driver_table[version] = set()
|
||||||
|
driver_table[version].add(driver)
|
||||||
|
for subdir, driver_name, file_prefix in DRIVER_MAP:
|
||||||
|
if subdir == ".":
|
||||||
|
add_driver(filter_versions(files, file_prefix, "c"), driver_name)
|
||||||
|
else:
|
||||||
|
tmp_files = next(walk(join(drivers_dir, subdir)))[2]
|
||||||
|
add_driver(filter_versions(tmp_files, file_prefix, "c"), driver_name)
|
||||||
|
return driver_table
|
||||||
|
|
||||||
|
def compute_table(dict_data):
|
||||||
|
"""
|
||||||
|
Create a table based on data generated by get_all_drivers().
|
||||||
|
|
||||||
|
:return: List of rows with "X" or "-", including column and row captions
|
||||||
|
(driver name / kernel version).
|
||||||
|
"""
|
||||||
|
keys = sorted(dict_data.keys(), reverse=True)
|
||||||
|
ans = [("Kernel", *DRIVERS),]
|
||||||
|
|
||||||
|
def parse_row(key):
|
||||||
|
row_set = dict_data[key]
|
||||||
|
row = []
|
||||||
|
for driver in DRIVERS:
|
||||||
|
if driver in row_set:
|
||||||
|
row.append("X")
|
||||||
|
else:
|
||||||
|
row.append("-")
|
||||||
|
return row
|
||||||
|
|
||||||
|
for key in keys:
|
||||||
|
c = "{}.{: <2}".format(*key)
|
||||||
|
ans.append([c] + parse_row(key))
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def get_max_width(row):
|
||||||
|
ans = 0
|
||||||
|
for cell in row:
|
||||||
|
if len(cell) > ans:
|
||||||
|
ans = len(cell)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def dump_markdown(table_data):
|
||||||
|
"""
|
||||||
|
Create a markdown table based on data from compute_table().
|
||||||
|
"""
|
||||||
|
width = get_max_width(table_data[0])
|
||||||
|
cell_fmt_center = "| {: ^" + str(width) + "} "
|
||||||
|
cell_fmt_left = "| {: <" + str(width) + "} "
|
||||||
|
cell_fmt_right = "| {: >" + str(width) + "} "
|
||||||
|
ans = cell_fmt_left.format(table_data[0][0])
|
||||||
|
for cell in table_data[0][1:]:
|
||||||
|
ans += cell_fmt_center.format(cell)
|
||||||
|
ans += '|\n|-' + "-" * width + ":|"
|
||||||
|
for i in range(len(table_data[0]) - 1):
|
||||||
|
ans += ':' + "-" * width + ':|'
|
||||||
|
for row in table_data[1:]:
|
||||||
|
ans += '\n' + cell_fmt_right.format(row[0])
|
||||||
|
for cell in row[1:]:
|
||||||
|
ans += cell_fmt_center.format(cell)
|
||||||
|
ans += '|'
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from sys import argv
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--markdown",
|
||||||
|
nargs=1,
|
||||||
|
help="Markdown output file",
|
||||||
|
type=argparse.FileType("w")
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"devices_dir",
|
||||||
|
nargs=1,
|
||||||
|
help="Devices driver source dir"
|
||||||
|
)
|
||||||
|
args = parser.parse_args(argv[1:])
|
||||||
|
table = compute_table(get_all_drivers(args.devices_dir[0]))
|
||||||
|
if args.markdown is not None:
|
||||||
|
with args.markdown[0] as f:
|
||||||
|
f.write(dump_markdown(table))
|
||||||
|
f.write('\n')
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
Device Drivers {#devicedrivers}
|
||||||
|
==============
|
||||||
|
|
||||||
|
This table contains a list of all available native drivers,
|
||||||
|
depending on the kernel version.
|
||||||
|
|
||||||
|
The `generic` and the `ccat` driver are independent of the kernel version.
|
||||||
|
|
||||||
|
To find out which native driver is required for your network card,
|
||||||
|
you can use `lspci -vv` or look in `/sys`:
|
||||||
|
```sh
|
||||||
|
admin@ipc:~> ls -l /sys/class/net/eth5/device/driver
|
||||||
|
lrwxrwxrwx 1 root root 0 6. Nov 15:35 /sys/class/net/eth5/device/driver -> ../../../../bus/pci/drivers/e1000
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```sh
|
||||||
|
admin@ipc:~> basename $(readlink /sys/class/net/eth5/device/driver)
|
||||||
|
e1000
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, `eth5` uses the `e1000` driver.
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -76,6 +76,14 @@ EXTRA_DIST = \
|
||||||
e1000-3.8-orig.h \
|
e1000-3.8-orig.h \
|
||||||
e1000-4.4-ethercat.h \
|
e1000-4.4-ethercat.h \
|
||||||
e1000-4.4-orig.h \
|
e1000-4.4-orig.h \
|
||||||
|
e1000-5.10-ethercat.h \
|
||||||
|
e1000-5.10-orig.h \
|
||||||
|
e1000-5.14-ethercat.h \
|
||||||
|
e1000-5.14-orig.h \
|
||||||
|
e1000-5.15-ethercat.h \
|
||||||
|
e1000-5.15-orig.h \
|
||||||
|
e1000-6.1-ethercat.h \
|
||||||
|
e1000-6.1-orig.h \
|
||||||
e1000_ethtool-2.6.13-ethercat.c \
|
e1000_ethtool-2.6.13-ethercat.c \
|
||||||
e1000_ethtool-2.6.13-orig.c \
|
e1000_ethtool-2.6.13-orig.c \
|
||||||
e1000_ethtool-2.6.18-ethercat.c \
|
e1000_ethtool-2.6.18-ethercat.c \
|
||||||
|
|
@ -122,6 +130,14 @@ EXTRA_DIST = \
|
||||||
e1000_ethtool-3.8-orig.c \
|
e1000_ethtool-3.8-orig.c \
|
||||||
e1000_ethtool-4.4-ethercat.c \
|
e1000_ethtool-4.4-ethercat.c \
|
||||||
e1000_ethtool-4.4-orig.c \
|
e1000_ethtool-4.4-orig.c \
|
||||||
|
e1000_ethtool-5.10-ethercat.c \
|
||||||
|
e1000_ethtool-5.10-orig.c \
|
||||||
|
e1000_ethtool-5.14-ethercat.c \
|
||||||
|
e1000_ethtool-5.14-orig.c \
|
||||||
|
e1000_ethtool-5.15-ethercat.c \
|
||||||
|
e1000_ethtool-5.15-orig.c \
|
||||||
|
e1000_ethtool-6.1-ethercat.c \
|
||||||
|
e1000_ethtool-6.1-orig.c \
|
||||||
e1000_hw-2.6.13-ethercat.c \
|
e1000_hw-2.6.13-ethercat.c \
|
||||||
e1000_hw-2.6.13-ethercat.h \
|
e1000_hw-2.6.13-ethercat.h \
|
||||||
e1000_hw-2.6.13-orig.c \
|
e1000_hw-2.6.13-orig.c \
|
||||||
|
|
@ -214,6 +230,22 @@ EXTRA_DIST = \
|
||||||
e1000_hw-4.4-ethercat.h \
|
e1000_hw-4.4-ethercat.h \
|
||||||
e1000_hw-4.4-orig.c \
|
e1000_hw-4.4-orig.c \
|
||||||
e1000_hw-4.4-orig.h \
|
e1000_hw-4.4-orig.h \
|
||||||
|
e1000_hw-5.10-ethercat.c \
|
||||||
|
e1000_hw-5.10-ethercat.h \
|
||||||
|
e1000_hw-5.10-orig.c \
|
||||||
|
e1000_hw-5.10-orig.h \
|
||||||
|
e1000_hw-5.14-ethercat.c \
|
||||||
|
e1000_hw-5.14-ethercat.h \
|
||||||
|
e1000_hw-5.14-orig.c \
|
||||||
|
e1000_hw-5.14-orig.h \
|
||||||
|
e1000_hw-5.15-ethercat.c \
|
||||||
|
e1000_hw-5.15-ethercat.h \
|
||||||
|
e1000_hw-5.15-orig.c \
|
||||||
|
e1000_hw-5.15-orig.h \
|
||||||
|
e1000_hw-6.1-ethercat.c \
|
||||||
|
e1000_hw-6.1-ethercat.h \
|
||||||
|
e1000_hw-6.1-orig.c \
|
||||||
|
e1000_hw-6.1-orig.h \
|
||||||
e1000_main-2.6.13-ethercat.c \
|
e1000_main-2.6.13-ethercat.c \
|
||||||
e1000_main-2.6.13-orig.c \
|
e1000_main-2.6.13-orig.c \
|
||||||
e1000_main-2.6.18-ethercat.c \
|
e1000_main-2.6.18-ethercat.c \
|
||||||
|
|
@ -260,6 +292,14 @@ EXTRA_DIST = \
|
||||||
e1000_main-3.8-orig.c \
|
e1000_main-3.8-orig.c \
|
||||||
e1000_main-4.4-ethercat.c \
|
e1000_main-4.4-ethercat.c \
|
||||||
e1000_main-4.4-orig.c \
|
e1000_main-4.4-orig.c \
|
||||||
|
e1000_main-5.10-ethercat.c \
|
||||||
|
e1000_main-5.10-orig.c \
|
||||||
|
e1000_main-5.14-ethercat.c \
|
||||||
|
e1000_main-5.14-orig.c \
|
||||||
|
e1000_main-5.15-ethercat.c \
|
||||||
|
e1000_main-5.15-orig.c \
|
||||||
|
e1000_main-6.1-ethercat.c \
|
||||||
|
e1000_main-6.1-orig.c \
|
||||||
e1000_osdep-2.6.13-ethercat.h \
|
e1000_osdep-2.6.13-ethercat.h \
|
||||||
e1000_osdep-2.6.13-orig.h \
|
e1000_osdep-2.6.13-orig.h \
|
||||||
e1000_osdep-2.6.18-ethercat.h \
|
e1000_osdep-2.6.18-ethercat.h \
|
||||||
|
|
@ -306,6 +346,14 @@ EXTRA_DIST = \
|
||||||
e1000_osdep-3.8-orig.h \
|
e1000_osdep-3.8-orig.h \
|
||||||
e1000_osdep-4.4-ethercat.h \
|
e1000_osdep-4.4-ethercat.h \
|
||||||
e1000_osdep-4.4-orig.h \
|
e1000_osdep-4.4-orig.h \
|
||||||
|
e1000_osdep-5.10-ethercat.h \
|
||||||
|
e1000_osdep-5.10-orig.h \
|
||||||
|
e1000_osdep-5.14-ethercat.h \
|
||||||
|
e1000_osdep-5.14-orig.h \
|
||||||
|
e1000_osdep-5.15-ethercat.h \
|
||||||
|
e1000_osdep-5.15-orig.h \
|
||||||
|
e1000_osdep-6.1-ethercat.h \
|
||||||
|
e1000_osdep-6.1-orig.h \
|
||||||
e1000_param-2.6.13-ethercat.c \
|
e1000_param-2.6.13-ethercat.c \
|
||||||
e1000_param-2.6.13-orig.c \
|
e1000_param-2.6.13-orig.c \
|
||||||
e1000_param-2.6.18-ethercat.c \
|
e1000_param-2.6.18-ethercat.c \
|
||||||
|
|
@ -351,6 +399,14 @@ EXTRA_DIST = \
|
||||||
e1000_param-3.8-ethercat.c \
|
e1000_param-3.8-ethercat.c \
|
||||||
e1000_param-3.8-orig.c \
|
e1000_param-3.8-orig.c \
|
||||||
e1000_param-4.4-ethercat.c \
|
e1000_param-4.4-ethercat.c \
|
||||||
e1000_param-4.4-orig.c
|
e1000_param-4.4-orig.c \
|
||||||
|
e1000_param-5.10-ethercat.c \
|
||||||
|
e1000_param-5.10-orig.c \
|
||||||
|
e1000_param-5.14-ethercat.c \
|
||||||
|
e1000_param-5.14-orig.c \
|
||||||
|
e1000_param-5.15-ethercat.c \
|
||||||
|
e1000_param-5.15-orig.c \
|
||||||
|
e1000_param-6.1-ethercat.c \
|
||||||
|
e1000_param-6.1-orig.c
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,357 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include "../ecdev.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw-5.10-ethercat.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
|
||||||
|
ec_device_t *ecdev;
|
||||||
|
unsigned long ec_watchdog_jiffies;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,352 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,357 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include "../ecdev.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw-5.14-ethercat.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
|
||||||
|
ec_device_t *ecdev;
|
||||||
|
unsigned long ec_watchdog_jiffies;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,352 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,357 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include "../ecdev.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw-5.15-ethercat.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
|
||||||
|
ec_device_t *ecdev;
|
||||||
|
unsigned long ec_watchdog_jiffies;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,352 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,357 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include "../ecdev.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw-6.1-ethercat.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
|
||||||
|
ec_device_t *ecdev;
|
||||||
|
unsigned long ec_watchdog_jiffies;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
|
|
@ -0,0 +1,352 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||||
|
|
||||||
|
#ifndef _E1000_H_
|
||||||
|
#define _E1000_H_
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
#include <net/pkt_sched.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <net/checksum.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
|
||||||
|
#define BAR_0 0
|
||||||
|
#define BAR_1 1
|
||||||
|
|
||||||
|
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||||
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||||
|
|
||||||
|
struct e1000_adapter;
|
||||||
|
|
||||||
|
#include "e1000_hw.h"
|
||||||
|
|
||||||
|
#define E1000_MAX_INTR 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||||
|
*/
|
||||||
|
#define E1000_CHECK_RESET_COUNT 50
|
||||||
|
|
||||||
|
/* TX/RX descriptor defines */
|
||||||
|
#define E1000_DEFAULT_TXD 256
|
||||||
|
#define E1000_MAX_TXD 256
|
||||||
|
#define E1000_MIN_TXD 48
|
||||||
|
#define E1000_MAX_82544_TXD 4096
|
||||||
|
|
||||||
|
#define E1000_DEFAULT_RXD 256
|
||||||
|
#define E1000_MAX_RXD 256
|
||||||
|
#define E1000_MIN_RXD 48
|
||||||
|
#define E1000_MAX_82544_RXD 4096
|
||||||
|
|
||||||
|
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||||
|
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||||
|
|
||||||
|
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||||
|
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||||
|
|
||||||
|
/* Supported Rx Buffer Sizes */
|
||||||
|
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||||
|
#define E1000_RXBUFFER_512 512
|
||||||
|
#define E1000_RXBUFFER_1024 1024
|
||||||
|
#define E1000_RXBUFFER_2048 2048
|
||||||
|
#define E1000_RXBUFFER_4096 4096
|
||||||
|
#define E1000_RXBUFFER_8192 8192
|
||||||
|
#define E1000_RXBUFFER_16384 16384
|
||||||
|
|
||||||
|
/* SmartSpeed delimiters */
|
||||||
|
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||||
|
#define E1000_SMARTSPEED_MAX 15
|
||||||
|
|
||||||
|
/* Packet Buffer allocations */
|
||||||
|
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||||
|
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||||
|
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||||
|
|
||||||
|
/* Flow Control Watermarks */
|
||||||
|
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||||
|
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||||
|
|
||||||
|
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||||
|
|
||||||
|
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||||
|
#define E1000_TX_QUEUE_WAKE 16
|
||||||
|
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||||
|
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||||
|
|
||||||
|
#define AUTO_ALL_MODES 0
|
||||||
|
#define E1000_EEPROM_82544_APM 0x0004
|
||||||
|
#define E1000_EEPROM_APME 0x0400
|
||||||
|
|
||||||
|
#ifndef E1000_MASTER_SLAVE
|
||||||
|
/* Switch to override PHY master/slave setting */
|
||||||
|
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define E1000_MNG_VLAN_NONE (-1)
|
||||||
|
|
||||||
|
/* wrapper around a pointer to a socket buffer,
|
||||||
|
* so a DMA handle can be stored along with the buffer
|
||||||
|
*/
|
||||||
|
struct e1000_tx_buffer {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t dma;
|
||||||
|
unsigned long time_stamp;
|
||||||
|
u16 length;
|
||||||
|
u16 next_to_watch;
|
||||||
|
bool mapped_as_page;
|
||||||
|
unsigned short segs;
|
||||||
|
unsigned int bytecount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_buffer {
|
||||||
|
union {
|
||||||
|
struct page *page; /* jumbo: alloc_page */
|
||||||
|
u8 *data; /* else, netdev_alloc_frag */
|
||||||
|
} rxbuf;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_tx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_tx_buffer *buffer_info;
|
||||||
|
|
||||||
|
u16 tdh;
|
||||||
|
u16 tdt;
|
||||||
|
bool last_tx_tso;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_rx_ring {
|
||||||
|
/* pointer to the descriptor ring memory */
|
||||||
|
void *desc;
|
||||||
|
/* physical address of the descriptor ring */
|
||||||
|
dma_addr_t dma;
|
||||||
|
/* length of descriptor ring in bytes */
|
||||||
|
unsigned int size;
|
||||||
|
/* number of descriptors in the ring */
|
||||||
|
unsigned int count;
|
||||||
|
/* next descriptor to associate a buffer with */
|
||||||
|
unsigned int next_to_use;
|
||||||
|
/* next descriptor to check for DD status bit */
|
||||||
|
unsigned int next_to_clean;
|
||||||
|
/* array of buffer information structs */
|
||||||
|
struct e1000_rx_buffer *buffer_info;
|
||||||
|
struct sk_buff *rx_skb_top;
|
||||||
|
|
||||||
|
/* cpu for rx queue */
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
u16 rdh;
|
||||||
|
u16 rdt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_DESC_UNUSED(R) \
|
||||||
|
({ \
|
||||||
|
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||||
|
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||||
|
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define E1000_RX_DESC_EXT(R, i) \
|
||||||
|
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||||
|
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||||
|
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||||
|
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||||
|
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||||
|
|
||||||
|
/* board specific private data structure */
|
||||||
|
|
||||||
|
struct e1000_adapter {
|
||||||
|
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||||
|
u16 mng_vlan_id;
|
||||||
|
u32 bd_number;
|
||||||
|
u32 rx_buffer_len;
|
||||||
|
u32 wol;
|
||||||
|
u32 smartspeed;
|
||||||
|
u32 en_mng_pt;
|
||||||
|
u16 link_speed;
|
||||||
|
u16 link_duplex;
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
unsigned int total_tx_bytes;
|
||||||
|
unsigned int total_tx_packets;
|
||||||
|
unsigned int total_rx_bytes;
|
||||||
|
unsigned int total_rx_packets;
|
||||||
|
/* Interrupt Throttle Rate */
|
||||||
|
u32 itr;
|
||||||
|
u32 itr_setting;
|
||||||
|
u16 tx_itr;
|
||||||
|
u16 rx_itr;
|
||||||
|
|
||||||
|
u8 fc_autoneg;
|
||||||
|
|
||||||
|
/* TX */
|
||||||
|
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||||
|
unsigned int restart_queue;
|
||||||
|
u32 txd_cmd;
|
||||||
|
u32 tx_int_delay;
|
||||||
|
u32 tx_abs_int_delay;
|
||||||
|
u32 gotcl;
|
||||||
|
u64 gotcl_old;
|
||||||
|
u64 tpt_old;
|
||||||
|
u64 colc_old;
|
||||||
|
u32 tx_timeout_count;
|
||||||
|
u32 tx_fifo_head;
|
||||||
|
u32 tx_head_addr;
|
||||||
|
u32 tx_fifo_size;
|
||||||
|
u8 tx_timeout_factor;
|
||||||
|
atomic_t tx_fifo_stall;
|
||||||
|
bool pcix_82544;
|
||||||
|
bool detect_tx_hung;
|
||||||
|
bool dump_buffers;
|
||||||
|
|
||||||
|
/* RX */
|
||||||
|
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int *work_done, int work_to_do);
|
||||||
|
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||||
|
struct e1000_rx_ring *rx_ring,
|
||||||
|
int cleaned_count);
|
||||||
|
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||||
|
struct napi_struct napi;
|
||||||
|
|
||||||
|
int num_tx_queues;
|
||||||
|
int num_rx_queues;
|
||||||
|
|
||||||
|
u64 hw_csum_err;
|
||||||
|
u64 hw_csum_good;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_int_delay;
|
||||||
|
u32 rx_abs_int_delay;
|
||||||
|
bool rx_csum;
|
||||||
|
u32 gorcl;
|
||||||
|
u64 gorcl_old;
|
||||||
|
|
||||||
|
/* OS defined structs */
|
||||||
|
struct net_device *netdev;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in e1000_hw.h */
|
||||||
|
struct e1000_hw hw;
|
||||||
|
struct e1000_hw_stats stats;
|
||||||
|
struct e1000_phy_info phy_info;
|
||||||
|
struct e1000_phy_stats phy_stats;
|
||||||
|
|
||||||
|
u32 test_icr;
|
||||||
|
struct e1000_tx_ring test_tx_ring;
|
||||||
|
struct e1000_rx_ring test_rx_ring;
|
||||||
|
|
||||||
|
int msg_enable;
|
||||||
|
|
||||||
|
/* to not mess up cache alignment, always add to the bottom */
|
||||||
|
bool tso_force;
|
||||||
|
bool smart_power_down; /* phy smart power down */
|
||||||
|
bool quad_port_a;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 eeprom_wol;
|
||||||
|
|
||||||
|
/* for ioport free */
|
||||||
|
int bars;
|
||||||
|
int need_ioport;
|
||||||
|
|
||||||
|
bool discarding;
|
||||||
|
|
||||||
|
struct work_struct reset_task;
|
||||||
|
struct delayed_work watchdog_task;
|
||||||
|
struct delayed_work fifo_stall_task;
|
||||||
|
struct delayed_work phy_info_task;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_state_t {
|
||||||
|
__E1000_TESTING,
|
||||||
|
__E1000_RESETTING,
|
||||||
|
__E1000_DOWN,
|
||||||
|
__E1000_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define e_dbg(format, arg...) \
|
||||||
|
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||||
|
#define e_err(msglvl, format, arg...) \
|
||||||
|
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_info(msglvl, format, arg...) \
|
||||||
|
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_warn(msglvl, format, arg...) \
|
||||||
|
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_notice(msglvl, format, arg...) \
|
||||||
|
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||||
|
#define e_dev_info(format, arg...) \
|
||||||
|
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_warn(format, arg...) \
|
||||||
|
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||||
|
#define e_dev_err(format, arg...) \
|
||||||
|
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||||
|
|
||||||
|
extern char e1000_driver_name[];
|
||||||
|
|
||||||
|
int e1000_open(struct net_device *netdev);
|
||||||
|
int e1000_close(struct net_device *netdev);
|
||||||
|
int e1000_up(struct e1000_adapter *adapter);
|
||||||
|
void e1000_down(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||||
|
void e1000_reset(struct e1000_adapter *adapter);
|
||||||
|
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||||
|
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||||
|
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||||
|
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||||
|
void e1000_power_up_phy(struct e1000_adapter *);
|
||||||
|
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter);
|
||||||
|
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||||
|
|
||||||
|
#endif /* _E1000_H_ */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
/* glue for the OS independent part of e1000
|
||||||
|
* includes register access macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _E1000_OSDEP_H_
|
||||||
|
#define _E1000_OSDEP_H_
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define CONFIG_RAM_BASE 0x60000
|
||||||
|
#define GBE_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
#define GBE_CONFIG_RAM_BASE \
|
||||||
|
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_BASE_VIRT \
|
||||||
|
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||||
|
(iowrite16_rep(base + offset, data, count))
|
||||||
|
|
||||||
|
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||||
|
(ioread16_rep(base + (offset << 1), data, count))
|
||||||
|
|
||||||
|
#define er32(reg) \
|
||||||
|
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg)))
|
||||||
|
|
||||||
|
#define ew32(reg, value) \
|
||||||
|
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||||
|
? E1000_##reg : E1000_82542_##reg))))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||||
|
writel((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||||
|
readl((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 2)))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||||
|
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||||
|
writew((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||||
|
readw((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
((offset) << 1)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||||
|
writeb((value), ((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset))))
|
||||||
|
|
||||||
|
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||||
|
readb((a)->hw_addr + \
|
||||||
|
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||||
|
(offset)))
|
||||||
|
|
||||||
|
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||||
|
writel((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||||
|
readl((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||||
|
writew((value), ((a)->flash_address + reg)))
|
||||||
|
|
||||||
|
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||||
|
readw((a)->flash_address + reg))
|
||||||
|
|
||||||
|
#endif /* _E1000_OSDEP_H_ */
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000-5.10-ethercat.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
#define AUTONEG_ADV_MASK 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
#define AUTONEG_ADV_MASK 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000-5.14-ethercat.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
#define AUTONEG_ADV_MASK 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
#define AUTONEG_ADV_MASK 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000-5.15-ethercat.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
#define AUTONEG_ADV_MASK 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,729 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
#define AUTONEG_ADV_MASK 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,727 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000-6.1-ethercat.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,727 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||||
|
|
||||||
|
#include "e1000.h"
|
||||||
|
|
||||||
|
/* This is the only thing that needs to be changed to adjust the
|
||||||
|
* maximum number of ports that the driver can manage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_MAX_NIC 32
|
||||||
|
|
||||||
|
#define OPTION_UNSET -1
|
||||||
|
#define OPTION_DISABLED 0
|
||||||
|
#define OPTION_ENABLED 1
|
||||||
|
|
||||||
|
/* All parameters are treated the same, as an integer array of values.
|
||||||
|
* This macro just reduces the need to repeat the same declaration code
|
||||||
|
* over and over (plus this helps to avoid typo bugs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||||
|
#define E1000_PARAM(X, desc) \
|
||||||
|
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||||
|
static unsigned int num_##X; \
|
||||||
|
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||||
|
MODULE_PARM_DESC(X, desc);
|
||||||
|
|
||||||
|
/* Transmit Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||||
|
|
||||||
|
/* Receive Descriptor Count
|
||||||
|
*
|
||||||
|
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||||
|
* Valid Range: 80-4096 for 82544 and newer
|
||||||
|
*
|
||||||
|
* Default Value: 256
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||||
|
|
||||||
|
/* User Specified Speed Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 10, 100, 1000
|
||||||
|
* - 0 - auto-negotiate at all supported speeds
|
||||||
|
* - 10 - only link at 10 Mbps
|
||||||
|
* - 100 - only link at 100 Mbps
|
||||||
|
* - 1000 - only link at 1000 Mbps
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Speed, "Speed setting");
|
||||||
|
|
||||||
|
/* User Specified Duplex Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-2
|
||||||
|
* - 0 - auto-negotiate for duplex
|
||||||
|
* - 1 - only link at half duplex
|
||||||
|
* - 2 - only link at full duplex
|
||||||
|
*
|
||||||
|
* Default Value: 0
|
||||||
|
*/
|
||||||
|
E1000_PARAM(Duplex, "Duplex setting");
|
||||||
|
|
||||||
|
/* Auto-negotiation Advertisement Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||||
|
*
|
||||||
|
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||||
|
* combinations should be advertised during auto-negotiation.
|
||||||
|
* The supported speed and duplex modes are listed below
|
||||||
|
*
|
||||||
|
* Bit 7 6 5 4 3 2 1 0
|
||||||
|
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||||
|
* Duplex Full Full Half Full Half
|
||||||
|
*
|
||||||
|
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||||
|
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||||
|
|
||||||
|
/* User Specified Flow Control Override
|
||||||
|
*
|
||||||
|
* Valid Range: 0-3
|
||||||
|
* - 0 - No Flow Control
|
||||||
|
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||||
|
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||||
|
* - 3 - Full Flow Control Support
|
||||||
|
*
|
||||||
|
* Default Value: Read flow control settings from the EEPROM
|
||||||
|
*/
|
||||||
|
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||||
|
|
||||||
|
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
* - 0 - disables all checksum offload
|
||||||
|
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||||
|
* on 82543 and newer -based NICs
|
||||||
|
*
|
||||||
|
* Default Value: 1
|
||||||
|
*/
|
||||||
|
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||||
|
|
||||||
|
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* Tx interrupt delay needs to typically be set to something non zero
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||||
|
#define DEFAULT_TIDV 8
|
||||||
|
#define MAX_TXDELAY 0xFFFF
|
||||||
|
#define MIN_TXDELAY 0
|
||||||
|
|
||||||
|
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_TADV 32
|
||||||
|
#define MAX_TXABSDELAY 0xFFFF
|
||||||
|
#define MIN_TXABSDELAY 0
|
||||||
|
|
||||||
|
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||||
|
* hardware will likely hang if you set this to anything but zero.
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||||
|
#define DEFAULT_RDTR 0
|
||||||
|
#define MAX_RXDELAY 0xFFFF
|
||||||
|
#define MIN_RXDELAY 0
|
||||||
|
|
||||||
|
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||||
|
*
|
||||||
|
* Valid Range: 0-65535
|
||||||
|
*/
|
||||||
|
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||||
|
#define DEFAULT_RADV 8
|
||||||
|
#define MAX_RXABSDELAY 0xFFFF
|
||||||
|
#define MIN_RXABSDELAY 0
|
||||||
|
|
||||||
|
/* Interrupt Throttle Rate (interrupts/sec)
|
||||||
|
*
|
||||||
|
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||||
|
#define DEFAULT_ITR 3
|
||||||
|
#define MAX_ITR 100000
|
||||||
|
#define MIN_ITR 100
|
||||||
|
|
||||||
|
/* Enable Smart Power Down of the PHY
|
||||||
|
*
|
||||||
|
* Valid Range: 0, 1
|
||||||
|
*
|
||||||
|
* Default Value: 0 (disabled)
|
||||||
|
*/
|
||||||
|
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||||
|
|
||||||
|
struct e1000_option {
|
||||||
|
enum { enable_option, range_option, list_option } type;
|
||||||
|
const char *name;
|
||||||
|
const char *err;
|
||||||
|
int def;
|
||||||
|
union {
|
||||||
|
struct { /* range_option info */
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
} r;
|
||||||
|
struct { /* list_option info */
|
||||||
|
int nr;
|
||||||
|
const struct e1000_opt_list { int i; char *str; } *p;
|
||||||
|
} l;
|
||||||
|
} arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int e1000_validate_option(unsigned int *value,
|
||||||
|
const struct e1000_option *opt,
|
||||||
|
struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (*value == OPTION_UNSET) {
|
||||||
|
*value = opt->def;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case enable_option:
|
||||||
|
switch (*value) {
|
||||||
|
case OPTION_ENABLED:
|
||||||
|
e_dev_info("%s Enabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
case OPTION_DISABLED:
|
||||||
|
e_dev_info("%s Disabled\n", opt->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case range_option:
|
||||||
|
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||||
|
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case list_option: {
|
||||||
|
int i;
|
||||||
|
const struct e1000_opt_list *ent;
|
||||||
|
|
||||||
|
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||||
|
ent = &opt->arg.l.p[i];
|
||||||
|
if (*value == ent->i) {
|
||||||
|
if (ent->str[0] != '\0')
|
||||||
|
e_dev_info("%s\n", ent->str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||||
|
opt->name, *value, opt->err);
|
||||||
|
*value = opt->def;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_options - Range Checking for Command Line Parameters
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* This routine checks all command line parameters for valid user
|
||||||
|
* input. If an invalid value is given, or if no user specified
|
||||||
|
* value exists, a default value is used. The final value is stored
|
||||||
|
* in a variable in the adapter structure.
|
||||||
|
**/
|
||||||
|
void e1000_check_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
if (bd >= E1000_MAX_NIC) {
|
||||||
|
e_dev_warn("Warning: no configuration for board #%i "
|
||||||
|
"using defaults for all values\n", bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* Transmit Descriptor Count */
|
||||||
|
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||||
|
.def = E1000_DEFAULT_TXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_TXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxDescriptors > bd) {
|
||||||
|
tx_ring->count = TxDescriptors[bd];
|
||||||
|
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||||
|
tx_ring->count = ALIGN(tx_ring->count,
|
||||||
|
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
tx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||||
|
tx_ring[i].count = tx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Receive Descriptor Count */
|
||||||
|
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||||
|
int i;
|
||||||
|
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Descriptors",
|
||||||
|
.err = "using default of "
|
||||||
|
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||||
|
.def = E1000_DEFAULT_RXD,
|
||||||
|
.arg = { .r = {
|
||||||
|
.min = E1000_MIN_RXD,
|
||||||
|
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||||
|
E1000_MAX_82544_RXD
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxDescriptors > bd) {
|
||||||
|
rx_ring->count = RxDescriptors[bd];
|
||||||
|
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||||
|
rx_ring->count = ALIGN(rx_ring->count,
|
||||||
|
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||||
|
} else {
|
||||||
|
rx_ring->count = opt.def;
|
||||||
|
}
|
||||||
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
|
rx_ring[i].count = rx_ring->count;
|
||||||
|
}
|
||||||
|
{ /* Checksum Offload Enable/Disable */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "Checksum Offload",
|
||||||
|
.err = "defaulting to Enabled",
|
||||||
|
.def = OPTION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_XsumRX > bd) {
|
||||||
|
unsigned int rx_csum = XsumRX[bd];
|
||||||
|
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||||
|
adapter->rx_csum = rx_csum;
|
||||||
|
} else {
|
||||||
|
adapter->rx_csum = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Flow Control */
|
||||||
|
|
||||||
|
static const struct e1000_opt_list fc_list[] = {
|
||||||
|
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||||
|
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||||
|
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||||
|
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||||
|
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||||
|
};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Flow Control",
|
||||||
|
.err = "reading default settings from EEPROM",
|
||||||
|
.def = E1000_FC_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||||
|
.p = fc_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_FlowControl > bd) {
|
||||||
|
unsigned int fc = FlowControl[bd];
|
||||||
|
e1000_validate_option(&fc, &opt, adapter);
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||||
|
} else {
|
||||||
|
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||||
|
.def = DEFAULT_TIDV,
|
||||||
|
.arg = { .r = { .min = MIN_TXDELAY,
|
||||||
|
.max = MAX_TXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxIntDelay > bd) {
|
||||||
|
adapter->tx_int_delay = TxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Transmit Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Transmit Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||||
|
.def = DEFAULT_TADV,
|
||||||
|
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||||
|
.max = MAX_TXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_TxAbsIntDelay > bd) {
|
||||||
|
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->tx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||||
|
.def = DEFAULT_RDTR,
|
||||||
|
.arg = { .r = { .min = MIN_RXDELAY,
|
||||||
|
.max = MAX_RXDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxIntDelay > bd) {
|
||||||
|
adapter->rx_int_delay = RxIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Receive Absolute Interrupt Delay */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Receive Absolute Interrupt Delay",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||||
|
.def = DEFAULT_RADV,
|
||||||
|
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||||
|
.max = MAX_RXABSDELAY }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_RxAbsIntDelay > bd) {
|
||||||
|
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||||
|
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||||
|
adapter);
|
||||||
|
} else {
|
||||||
|
adapter->rx_abs_int_delay = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Interrupt Throttling Rate */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = range_option,
|
||||||
|
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||||
|
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||||
|
.def = DEFAULT_ITR,
|
||||||
|
.arg = { .r = { .min = MIN_ITR,
|
||||||
|
.max = MAX_ITR }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_InterruptThrottleRate > bd) {
|
||||||
|
adapter->itr = InterruptThrottleRate[bd];
|
||||||
|
switch (adapter->itr) {
|
||||||
|
case 0:
|
||||||
|
e_dev_info("%s turned off\n", opt.name);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
e_dev_info("%s set to dynamic mode\n",
|
||||||
|
opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
e_dev_info("%s set to dynamic conservative "
|
||||||
|
"mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
e_dev_info("%s set to simplified "
|
||||||
|
"(2000-8000) ints mode\n", opt.name);
|
||||||
|
adapter->itr_setting = adapter->itr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e1000_validate_option(&adapter->itr, &opt,
|
||||||
|
adapter);
|
||||||
|
/* save the setting, because the dynamic bits
|
||||||
|
* change itr.
|
||||||
|
* clear the lower two bits because they are
|
||||||
|
* used as control
|
||||||
|
*/
|
||||||
|
adapter->itr_setting = adapter->itr & ~3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter->itr_setting = opt.def;
|
||||||
|
adapter->itr = 20000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Smart Power Down */
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = enable_option,
|
||||||
|
.name = "PHY Smart Power Down",
|
||||||
|
.err = "defaulting to Disabled",
|
||||||
|
.def = OPTION_DISABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_SmartPowerDownEnable > bd) {
|
||||||
|
unsigned int spd = SmartPowerDownEnable[bd];
|
||||||
|
e1000_validate_option(&spd, &opt, adapter);
|
||||||
|
adapter->smart_power_down = spd;
|
||||||
|
} else {
|
||||||
|
adapter->smart_power_down = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (adapter->hw.media_type) {
|
||||||
|
case e1000_media_type_fiber:
|
||||||
|
case e1000_media_type_internal_serdes:
|
||||||
|
e1000_check_fiber_options(adapter);
|
||||||
|
break;
|
||||||
|
case e1000_media_type_copper:
|
||||||
|
e1000_check_copper_options(adapter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on fiber adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||||
|
"ignored\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||||
|
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||||
|
"adapters, parameter ignored\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||||
|
* @adapter: board private structure
|
||||||
|
*
|
||||||
|
* Handles speed and duplex options on copper adapters
|
||||||
|
**/
|
||||||
|
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct e1000_option opt;
|
||||||
|
unsigned int speed, dplx, an;
|
||||||
|
int bd = adapter->bd_number;
|
||||||
|
|
||||||
|
{ /* Speed */
|
||||||
|
static const struct e1000_opt_list speed_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ SPEED_10, "" },
|
||||||
|
{ SPEED_100, "" },
|
||||||
|
{ SPEED_1000, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Speed",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||||
|
.p = speed_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Speed > bd) {
|
||||||
|
speed = Speed[bd];
|
||||||
|
e1000_validate_option(&speed, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
speed = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ /* Duplex */
|
||||||
|
static const struct e1000_opt_list dplx_list[] = {
|
||||||
|
{ 0, "" },
|
||||||
|
{ HALF_DUPLEX, "" },
|
||||||
|
{ FULL_DUPLEX, "" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "Duplex",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = 0,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||||
|
.p = dplx_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_Duplex > bd) {
|
||||||
|
dplx = Duplex[bd];
|
||||||
|
e1000_validate_option(&dplx, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
dplx = opt.def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||||
|
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||||
|
"parameter ignored\n");
|
||||||
|
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||||
|
} else { /* Autoneg */
|
||||||
|
static const struct e1000_opt_list an_list[] =
|
||||||
|
#define AA "AutoNeg advertising "
|
||||||
|
{{ 0x01, AA "10/HD" },
|
||||||
|
{ 0x02, AA "10/FD" },
|
||||||
|
{ 0x03, AA "10/FD, 10/HD" },
|
||||||
|
{ 0x04, AA "100/HD" },
|
||||||
|
{ 0x05, AA "100/HD, 10/HD" },
|
||||||
|
{ 0x06, AA "100/HD, 10/FD" },
|
||||||
|
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x08, AA "100/FD" },
|
||||||
|
{ 0x09, AA "100/FD, 10/HD" },
|
||||||
|
{ 0x0a, AA "100/FD, 10/FD" },
|
||||||
|
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x0c, AA "100/FD, 100/HD" },
|
||||||
|
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x20, AA "1000/FD" },
|
||||||
|
{ 0x21, AA "1000/FD, 10/HD" },
|
||||||
|
{ 0x22, AA "1000/FD, 10/FD" },
|
||||||
|
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x24, AA "1000/FD, 100/HD" },
|
||||||
|
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||||
|
{ 0x28, AA "1000/FD, 100/FD" },
|
||||||
|
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||||
|
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||||
|
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||||
|
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||||
|
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||||
|
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||||
|
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||||
|
|
||||||
|
opt = (struct e1000_option) {
|
||||||
|
.type = list_option,
|
||||||
|
.name = "AutoNeg",
|
||||||
|
.err = "parameter ignored",
|
||||||
|
.def = AUTONEG_ADV_DEFAULT,
|
||||||
|
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||||
|
.p = an_list }}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (num_AutoNeg > bd) {
|
||||||
|
an = AutoNeg[bd];
|
||||||
|
e1000_validate_option(&an, &opt, adapter);
|
||||||
|
} else {
|
||||||
|
an = opt.def;
|
||||||
|
}
|
||||||
|
adapter->hw.autoneg_advertised = an;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (speed + dplx) {
|
||||||
|
case 0:
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||||
|
e_dev_info("Speed and duplex autonegotiation "
|
||||||
|
"enabled\n");
|
||||||
|
break;
|
||||||
|
case HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_100_HALF;
|
||||||
|
break;
|
||||||
|
case FULL_DUPLEX:
|
||||||
|
e_dev_info("Full Duplex specified without Speed\n");
|
||||||
|
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||||
|
ADVERTISE_100_FULL |
|
||||||
|
ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10:
|
||||||
|
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||||
|
ADVERTISE_10_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_10 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||||
|
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||||
|
ADVERTISE_100_FULL;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_100 + FULL_DUPLEX:
|
||||||
|
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||||
|
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||||
|
adapter->hw.autoneg_advertised = 0;
|
||||||
|
break;
|
||||||
|
case SPEED_1000:
|
||||||
|
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||||
|
goto full_duplex_only;
|
||||||
|
case SPEED_1000 + HALF_DUPLEX:
|
||||||
|
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||||
|
fallthrough;
|
||||||
|
case SPEED_1000 + FULL_DUPLEX:
|
||||||
|
full_duplex_only:
|
||||||
|
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||||
|
"only\n");
|
||||||
|
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||||
|
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||||
|
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||||
|
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||||
|
"Setting MDI-X to a compatible value.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -21,7 +21,9 @@ for f in $KERNELDIR/drivers/net/ethernet/intel/e1000/*.[ch]; do
|
||||||
cp -v $o $e
|
cp -v $o $e
|
||||||
op=${b/\./-$PREVER-orig.}
|
op=${b/\./-$PREVER-orig.}
|
||||||
ep=${b/\./-$PREVER-ethercat.}
|
ep=${b/\./-$PREVER-ethercat.}
|
||||||
diff -u $op $ep | patch -p1 $e
|
diff -p -u $op $ep | patch -p1 $e
|
||||||
sed -i s/$PREVER-ethercat.h/$KERNELVER-ethercat.h/ $e
|
sed -i s/$PREVER-ethercat.h/$KERNELVER-ethercat.h/ $e
|
||||||
git add $o $e
|
git add $o $e
|
||||||
|
echo -e "\t$e \\\\\n\t$o \\\\" >> Makefile.am
|
||||||
done
|
done
|
||||||
|
echo "Remember to update Makefile.am!"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2017 Florian Pose, Ingenieurgemeinschaft IgH
|
||||||
|
#
|
||||||
|
# This file is part of the IgH EtherCAT Master.
|
||||||
|
#
|
||||||
|
# The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License version 2, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
# Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with the IgH EtherCAT Master; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
# ---
|
||||||
|
#
|
||||||
|
# The license mentioned above concerns the source code only. Using the
|
||||||
|
# EtherCAT technology and brand is only permitted in compliance with the
|
||||||
|
# industrial property and similar rights of Beckhoff Automation GmbH.
|
||||||
|
#
|
||||||
|
# ---
|
||||||
|
#
|
||||||
|
# vim: syntax=make
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TOPDIR := $(src)/../..
|
||||||
|
|
||||||
|
REV := $(shell if test -s $(TOPDIR)/revision; then \
|
||||||
|
cat $(TOPDIR)/revision; \
|
||||||
|
else \
|
||||||
|
git -C $(TOPDIR) describe 2>/dev/null || echo "unknown"; \
|
||||||
|
fi)
|
||||||
|
|
||||||
|
ifeq (@ENABLE_GENET@,1)
|
||||||
|
obj-m += ec_genet.o
|
||||||
|
ec_genet-objs := \
|
||||||
|
bcmgenet-@KERNEL_GENET@-ethercat.o \
|
||||||
|
bcmmii-@KERNEL_GENET@-ethercat.o \
|
||||||
|
bcmgenet_wol-@KERNEL_GENET@-ethercat.o
|
||||||
|
|
||||||
|
CFLAGS_bcmgenet-@KERNEL_GENET@-ethercat.o = -DREV="\"$(REV)\""
|
||||||
|
endif
|
||||||
|
|
||||||
|
KBUILD_EXTRA_SYMBOLS := \
|
||||||
|
@abs_top_builddir@/$(LINUX_SYMVERS) \
|
||||||
|
@abs_top_builddir@/master/$(LINUX_SYMVERS)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006-2021 Florian Pose, Ingenieurgemeinschaft IgH
|
||||||
|
#
|
||||||
|
# This file is part of the IgH EtherCAT Master.
|
||||||
|
#
|
||||||
|
# The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License version 2, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
# Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with the IgH EtherCAT Master; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
# ---
|
||||||
|
#
|
||||||
|
# The license mentioned above concerns the source code only. Using the
|
||||||
|
# EtherCAT technology and brand is only permitted in compliance with the
|
||||||
|
# industrial property and similar rights of Beckhoff Automation GmbH.
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
include $(top_srcdir)/Makefile.kbuild
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
bcmgenet-6.1-ethercat.c \
|
||||||
|
bcmgenet-6.1-ethercat.h \
|
||||||
|
bcmgenet-6.1-orig.c \
|
||||||
|
bcmgenet-6.1-orig.h \
|
||||||
|
bcmgenet_wol-6.1-ethercat.c \
|
||||||
|
bcmgenet_wol-6.1-orig.c \
|
||||||
|
bcmmii-6.1-ethercat.c \
|
||||||
|
bcmmii-6.1-orig.c
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,714 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2020 Broadcom
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BCMGENET_H__
|
||||||
|
#define __BCMGENET_H__
|
||||||
|
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/dim.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
|
||||||
|
#include "unimac-6.1-ethercat.h"
|
||||||
|
|
||||||
|
/* EtherCAT header file */
|
||||||
|
#include "../ecdev.h"
|
||||||
|
|
||||||
|
/* total number of Buffer Descriptors, same for Rx/Tx */
|
||||||
|
#define TOTAL_DESC 256
|
||||||
|
|
||||||
|
/* which ring is descriptor based */
|
||||||
|
#define DESC_INDEX 16
|
||||||
|
|
||||||
|
/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
|
||||||
|
* 1536 is multiple of 256 bytes
|
||||||
|
*/
|
||||||
|
#define ENET_BRCM_TAG_LEN 6
|
||||||
|
#define ENET_PAD 8
|
||||||
|
#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
|
||||||
|
ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
|
||||||
|
#define DMA_MAX_BURST_LENGTH 0x10
|
||||||
|
|
||||||
|
/* misc. configuration */
|
||||||
|
#define MAX_NUM_OF_FS_RULES 16
|
||||||
|
#define CLEAR_ALL_HFB 0xFF
|
||||||
|
#define DMA_FC_THRESH_HI (TOTAL_DESC >> 4)
|
||||||
|
#define DMA_FC_THRESH_LO 5
|
||||||
|
|
||||||
|
/* 64B receive/transmit status block */
|
||||||
|
struct status_64 {
|
||||||
|
u32 length_status; /* length and peripheral status */
|
||||||
|
u32 ext_status; /* Extended status*/
|
||||||
|
u32 rx_csum; /* partial rx checksum */
|
||||||
|
u32 unused1[9]; /* unused */
|
||||||
|
u32 tx_csum_info; /* Tx checksum info. */
|
||||||
|
u32 unused2[3]; /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Rx status bits */
|
||||||
|
#define STATUS_RX_EXT_MASK 0x1FFFFF
|
||||||
|
#define STATUS_RX_CSUM_MASK 0xFFFF
|
||||||
|
#define STATUS_RX_CSUM_OK 0x10000
|
||||||
|
#define STATUS_RX_CSUM_FR 0x20000
|
||||||
|
#define STATUS_RX_PROTO_TCP 0
|
||||||
|
#define STATUS_RX_PROTO_UDP 1
|
||||||
|
#define STATUS_RX_PROTO_ICMP 2
|
||||||
|
#define STATUS_RX_PROTO_OTHER 3
|
||||||
|
#define STATUS_RX_PROTO_MASK 3
|
||||||
|
#define STATUS_RX_PROTO_SHIFT 18
|
||||||
|
#define STATUS_FILTER_INDEX_MASK 0xFFFF
|
||||||
|
/* Tx status bits */
|
||||||
|
#define STATUS_TX_CSUM_START_MASK 0X7FFF
|
||||||
|
#define STATUS_TX_CSUM_START_SHIFT 16
|
||||||
|
#define STATUS_TX_CSUM_PROTO_UDP 0x8000
|
||||||
|
#define STATUS_TX_CSUM_OFFSET_MASK 0x7FFF
|
||||||
|
#define STATUS_TX_CSUM_LV 0x80000000
|
||||||
|
|
||||||
|
/* DMA Descriptor */
|
||||||
|
#define DMA_DESC_LENGTH_STATUS 0x00 /* in bytes of data in buffer */
|
||||||
|
#define DMA_DESC_ADDRESS_LO 0x04 /* lower bits of PA */
|
||||||
|
#define DMA_DESC_ADDRESS_HI 0x08 /* upper 32 bits of PA, GENETv4+ */
|
||||||
|
|
||||||
|
/* Rx/Tx common counter group */
|
||||||
|
struct bcmgenet_pkt_counters {
|
||||||
|
u32 cnt_64; /* RO Received/Transmited 64 bytes packet */
|
||||||
|
u32 cnt_127; /* RO Rx/Tx 127 bytes packet */
|
||||||
|
u32 cnt_255; /* RO Rx/Tx 65-255 bytes packet */
|
||||||
|
u32 cnt_511; /* RO Rx/Tx 256-511 bytes packet */
|
||||||
|
u32 cnt_1023; /* RO Rx/Tx 512-1023 bytes packet */
|
||||||
|
u32 cnt_1518; /* RO Rx/Tx 1024-1518 bytes packet */
|
||||||
|
u32 cnt_mgv; /* RO Rx/Tx 1519-1522 good VLAN packet */
|
||||||
|
u32 cnt_2047; /* RO Rx/Tx 1522-2047 bytes packet*/
|
||||||
|
u32 cnt_4095; /* RO Rx/Tx 2048-4095 bytes packet*/
|
||||||
|
u32 cnt_9216; /* RO Rx/Tx 4096-9216 bytes packet*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/* RSV, Receive Status Vector */
|
||||||
|
struct bcmgenet_rx_counters {
|
||||||
|
struct bcmgenet_pkt_counters pkt_cnt;
|
||||||
|
u32 pkt; /* RO (0x428) Received pkt count*/
|
||||||
|
u32 bytes; /* RO Received byte count */
|
||||||
|
u32 mca; /* RO # of Received multicast pkt */
|
||||||
|
u32 bca; /* RO # of Receive broadcast pkt */
|
||||||
|
u32 fcs; /* RO # of Received FCS error */
|
||||||
|
u32 cf; /* RO # of Received control frame pkt*/
|
||||||
|
u32 pf; /* RO # of Received pause frame pkt */
|
||||||
|
u32 uo; /* RO # of unknown op code pkt */
|
||||||
|
u32 aln; /* RO # of alignment error count */
|
||||||
|
u32 flr; /* RO # of frame length out of range count */
|
||||||
|
u32 cde; /* RO # of code error pkt */
|
||||||
|
u32 fcr; /* RO # of carrier sense error pkt */
|
||||||
|
u32 ovr; /* RO # of oversize pkt*/
|
||||||
|
u32 jbr; /* RO # of jabber count */
|
||||||
|
u32 mtue; /* RO # of MTU error pkt*/
|
||||||
|
u32 pok; /* RO # of Received good pkt */
|
||||||
|
u32 uc; /* RO # of unicast pkt */
|
||||||
|
u32 ppp; /* RO # of PPP pkt */
|
||||||
|
u32 rcrc; /* RO (0x470),# of CRC match pkt */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TSV, Transmit Status Vector */
|
||||||
|
struct bcmgenet_tx_counters {
|
||||||
|
struct bcmgenet_pkt_counters pkt_cnt;
|
||||||
|
u32 pkts; /* RO (0x4a8) Transmited pkt */
|
||||||
|
u32 mca; /* RO # of xmited multicast pkt */
|
||||||
|
u32 bca; /* RO # of xmited broadcast pkt */
|
||||||
|
u32 pf; /* RO # of xmited pause frame count */
|
||||||
|
u32 cf; /* RO # of xmited control frame count */
|
||||||
|
u32 fcs; /* RO # of xmited FCS error count */
|
||||||
|
u32 ovr; /* RO # of xmited oversize pkt */
|
||||||
|
u32 drf; /* RO # of xmited deferral pkt */
|
||||||
|
u32 edf; /* RO # of xmited Excessive deferral pkt*/
|
||||||
|
u32 scl; /* RO # of xmited single collision pkt */
|
||||||
|
u32 mcl; /* RO # of xmited multiple collision pkt*/
|
||||||
|
u32 lcl; /* RO # of xmited late collision pkt */
|
||||||
|
u32 ecl; /* RO # of xmited excessive collision pkt*/
|
||||||
|
u32 frg; /* RO # of xmited fragments pkt*/
|
||||||
|
u32 ncl; /* RO # of xmited total collision count */
|
||||||
|
u32 jbr; /* RO # of xmited jabber count*/
|
||||||
|
u32 bytes; /* RO # of xmited byte count */
|
||||||
|
u32 pok; /* RO # of xmited good pkt */
|
||||||
|
u32 uc; /* RO (0x0x4f0)# of xmited unitcast pkt */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_mib_counters {
|
||||||
|
struct bcmgenet_rx_counters rx;
|
||||||
|
struct bcmgenet_tx_counters tx;
|
||||||
|
u32 rx_runt_cnt;
|
||||||
|
u32 rx_runt_fcs;
|
||||||
|
u32 rx_runt_fcs_align;
|
||||||
|
u32 rx_runt_bytes;
|
||||||
|
u32 rbuf_ovflow_cnt;
|
||||||
|
u32 rbuf_err_cnt;
|
||||||
|
u32 mdf_err_cnt;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_dma_failed;
|
||||||
|
u32 tx_dma_failed;
|
||||||
|
u32 tx_realloc_tsb;
|
||||||
|
u32 tx_realloc_tsb_failed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UMAC_MIB_START 0x400
|
||||||
|
|
||||||
|
#define UMAC_MDIO_CMD 0x614
|
||||||
|
#define MDIO_START_BUSY (1 << 29)
|
||||||
|
#define MDIO_READ_FAIL (1 << 28)
|
||||||
|
#define MDIO_RD (2 << 26)
|
||||||
|
#define MDIO_WR (1 << 26)
|
||||||
|
#define MDIO_PMD_SHIFT 21
|
||||||
|
#define MDIO_PMD_MASK 0x1F
|
||||||
|
#define MDIO_REG_SHIFT 16
|
||||||
|
#define MDIO_REG_MASK 0x1F
|
||||||
|
|
||||||
|
#define UMAC_RBUF_OVFL_CNT_V1 0x61C
|
||||||
|
#define RBUF_OVFL_CNT_V2 0x80
|
||||||
|
#define RBUF_OVFL_CNT_V3PLUS 0x94
|
||||||
|
|
||||||
|
#define UMAC_MPD_CTRL 0x620
|
||||||
|
#define MPD_EN (1 << 0)
|
||||||
|
#define MPD_PW_EN (1 << 27)
|
||||||
|
#define MPD_MSEQ_LEN_SHIFT 16
|
||||||
|
#define MPD_MSEQ_LEN_MASK 0xFF
|
||||||
|
|
||||||
|
#define UMAC_MPD_PW_MS 0x624
|
||||||
|
#define UMAC_MPD_PW_LS 0x628
|
||||||
|
#define UMAC_RBUF_ERR_CNT_V1 0x634
|
||||||
|
#define RBUF_ERR_CNT_V2 0x84
|
||||||
|
#define RBUF_ERR_CNT_V3PLUS 0x98
|
||||||
|
#define UMAC_MDF_ERR_CNT 0x638
|
||||||
|
#define UMAC_MDF_CTRL 0x650
|
||||||
|
#define UMAC_MDF_ADDR 0x654
|
||||||
|
#define UMAC_MIB_CTRL 0x580
|
||||||
|
#define MIB_RESET_RX (1 << 0)
|
||||||
|
#define MIB_RESET_RUNT (1 << 1)
|
||||||
|
#define MIB_RESET_TX (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_CTRL 0x00
|
||||||
|
#define RBUF_64B_EN (1 << 0)
|
||||||
|
#define RBUF_ALIGN_2B (1 << 1)
|
||||||
|
#define RBUF_BAD_DIS (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_STATUS 0x0C
|
||||||
|
#define RBUF_STATUS_WOL (1 << 0)
|
||||||
|
#define RBUF_STATUS_MPD_INTR_ACTIVE (1 << 1)
|
||||||
|
#define RBUF_STATUS_ACPI_INTR_ACTIVE (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_CHK_CTRL 0x14
|
||||||
|
#define RBUF_RXCHK_EN (1 << 0)
|
||||||
|
#define RBUF_SKIP_FCS (1 << 4)
|
||||||
|
#define RBUF_L3_PARSE_DIS (1 << 5)
|
||||||
|
|
||||||
|
#define RBUF_ENERGY_CTRL 0x9c
|
||||||
|
#define RBUF_EEE_EN (1 << 0)
|
||||||
|
#define RBUF_PM_EN (1 << 1)
|
||||||
|
|
||||||
|
#define RBUF_TBUF_SIZE_CTRL 0xb4
|
||||||
|
|
||||||
|
#define RBUF_HFB_CTRL_V1 0x38
|
||||||
|
#define RBUF_HFB_FILTER_EN_SHIFT 16
|
||||||
|
#define RBUF_HFB_FILTER_EN_MASK 0xffff0000
|
||||||
|
#define RBUF_HFB_EN (1 << 0)
|
||||||
|
#define RBUF_HFB_256B (1 << 1)
|
||||||
|
#define RBUF_ACPI_EN (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_HFB_LEN_V1 0x3C
|
||||||
|
#define RBUF_FLTR_LEN_MASK 0xFF
|
||||||
|
#define RBUF_FLTR_LEN_SHIFT 8
|
||||||
|
|
||||||
|
#define TBUF_CTRL 0x00
|
||||||
|
#define TBUF_64B_EN (1 << 0)
|
||||||
|
#define TBUF_BP_MC 0x0C
|
||||||
|
#define TBUF_ENERGY_CTRL 0x14
|
||||||
|
#define TBUF_EEE_EN (1 << 0)
|
||||||
|
#define TBUF_PM_EN (1 << 1)
|
||||||
|
|
||||||
|
#define TBUF_CTRL_V1 0x80
|
||||||
|
#define TBUF_BP_MC_V1 0xA0
|
||||||
|
|
||||||
|
#define HFB_CTRL 0x00
|
||||||
|
#define HFB_FLT_ENABLE_V3PLUS 0x04
|
||||||
|
#define HFB_FLT_LEN_V2 0x04
|
||||||
|
#define HFB_FLT_LEN_V3PLUS 0x1C
|
||||||
|
|
||||||
|
/* uniMac intrl2 registers */
|
||||||
|
#define INTRL2_CPU_STAT 0x00
|
||||||
|
#define INTRL2_CPU_SET 0x04
|
||||||
|
#define INTRL2_CPU_CLEAR 0x08
|
||||||
|
#define INTRL2_CPU_MASK_STATUS 0x0C
|
||||||
|
#define INTRL2_CPU_MASK_SET 0x10
|
||||||
|
#define INTRL2_CPU_MASK_CLEAR 0x14
|
||||||
|
|
||||||
|
/* INTRL2 instance 0 definitions */
|
||||||
|
#define UMAC_IRQ_SCB (1 << 0)
|
||||||
|
#define UMAC_IRQ_EPHY (1 << 1)
|
||||||
|
#define UMAC_IRQ_PHY_DET_R (1 << 2)
|
||||||
|
#define UMAC_IRQ_PHY_DET_F (1 << 3)
|
||||||
|
#define UMAC_IRQ_LINK_UP (1 << 4)
|
||||||
|
#define UMAC_IRQ_LINK_DOWN (1 << 5)
|
||||||
|
#define UMAC_IRQ_LINK_EVENT (UMAC_IRQ_LINK_UP | UMAC_IRQ_LINK_DOWN)
|
||||||
|
#define UMAC_IRQ_UMAC (1 << 6)
|
||||||
|
#define UMAC_IRQ_UMAC_TSV (1 << 7)
|
||||||
|
#define UMAC_IRQ_TBUF_UNDERRUN (1 << 8)
|
||||||
|
#define UMAC_IRQ_RBUF_OVERFLOW (1 << 9)
|
||||||
|
#define UMAC_IRQ_HFB_SM (1 << 10)
|
||||||
|
#define UMAC_IRQ_HFB_MM (1 << 11)
|
||||||
|
#define UMAC_IRQ_MPD_R (1 << 12)
|
||||||
|
#define UMAC_IRQ_WAKE_EVENT (UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM | \
|
||||||
|
UMAC_IRQ_MPD_R)
|
||||||
|
#define UMAC_IRQ_RXDMA_MBDONE (1 << 13)
|
||||||
|
#define UMAC_IRQ_RXDMA_PDONE (1 << 14)
|
||||||
|
#define UMAC_IRQ_RXDMA_BDONE (1 << 15)
|
||||||
|
#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
|
||||||
|
#define UMAC_IRQ_TXDMA_MBDONE (1 << 16)
|
||||||
|
#define UMAC_IRQ_TXDMA_PDONE (1 << 17)
|
||||||
|
#define UMAC_IRQ_TXDMA_BDONE (1 << 18)
|
||||||
|
#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
|
||||||
|
|
||||||
|
/* Only valid for GENETv3+ */
|
||||||
|
#define UMAC_IRQ_MDIO_DONE (1 << 23)
|
||||||
|
#define UMAC_IRQ_MDIO_ERROR (1 << 24)
|
||||||
|
|
||||||
|
/* INTRL2 instance 1 definitions */
|
||||||
|
#define UMAC_IRQ1_TX_INTR_MASK 0xFFFF
|
||||||
|
#define UMAC_IRQ1_RX_INTR_MASK 0xFFFF
|
||||||
|
#define UMAC_IRQ1_RX_INTR_SHIFT 16
|
||||||
|
|
||||||
|
/* Register block offsets */
|
||||||
|
#define GENET_SYS_OFF 0x0000
|
||||||
|
#define GENET_GR_BRIDGE_OFF 0x0040
|
||||||
|
#define GENET_EXT_OFF 0x0080
|
||||||
|
#define GENET_INTRL2_0_OFF 0x0200
|
||||||
|
#define GENET_INTRL2_1_OFF 0x0240
|
||||||
|
#define GENET_RBUF_OFF 0x0300
|
||||||
|
#define GENET_UMAC_OFF 0x0800
|
||||||
|
|
||||||
|
/* SYS block offsets and register definitions */
|
||||||
|
#define SYS_REV_CTRL 0x00
|
||||||
|
#define SYS_PORT_CTRL 0x04
|
||||||
|
#define PORT_MODE_INT_EPHY 0
|
||||||
|
#define PORT_MODE_INT_GPHY 1
|
||||||
|
#define PORT_MODE_EXT_EPHY 2
|
||||||
|
#define PORT_MODE_EXT_GPHY 3
|
||||||
|
#define PORT_MODE_EXT_RVMII_25 (4 | BIT(4))
|
||||||
|
#define PORT_MODE_EXT_RVMII_50 4
|
||||||
|
#define LED_ACT_SOURCE_MAC (1 << 9)
|
||||||
|
|
||||||
|
#define SYS_RBUF_FLUSH_CTRL 0x08
|
||||||
|
#define SYS_TBUF_FLUSH_CTRL 0x0C
|
||||||
|
#define RBUF_FLUSH_CTRL_V1 0x04
|
||||||
|
|
||||||
|
/* Ext block register offsets and definitions */
|
||||||
|
#define EXT_EXT_PWR_MGMT 0x00
|
||||||
|
#define EXT_PWR_DOWN_BIAS (1 << 0)
|
||||||
|
#define EXT_PWR_DOWN_DLL (1 << 1)
|
||||||
|
#define EXT_PWR_DOWN_PHY (1 << 2)
|
||||||
|
#define EXT_PWR_DN_EN_LD (1 << 3)
|
||||||
|
#define EXT_ENERGY_DET (1 << 4)
|
||||||
|
#define EXT_IDDQ_FROM_PHY (1 << 5)
|
||||||
|
#define EXT_IDDQ_GLBL_PWR (1 << 7)
|
||||||
|
#define EXT_PHY_RESET (1 << 8)
|
||||||
|
#define EXT_ENERGY_DET_MASK (1 << 12)
|
||||||
|
#define EXT_PWR_DOWN_PHY_TX (1 << 16)
|
||||||
|
#define EXT_PWR_DOWN_PHY_RX (1 << 17)
|
||||||
|
#define EXT_PWR_DOWN_PHY_SD (1 << 18)
|
||||||
|
#define EXT_PWR_DOWN_PHY_RD (1 << 19)
|
||||||
|
#define EXT_PWR_DOWN_PHY_EN (1 << 20)
|
||||||
|
|
||||||
|
#define EXT_RGMII_OOB_CTRL 0x0C
|
||||||
|
#define RGMII_MODE_EN_V123 (1 << 0)
|
||||||
|
#define RGMII_LINK (1 << 4)
|
||||||
|
#define OOB_DISABLE (1 << 5)
|
||||||
|
#define RGMII_MODE_EN (1 << 6)
|
||||||
|
#define ID_MODE_DIS (1 << 16)
|
||||||
|
|
||||||
|
#define EXT_GPHY_CTRL 0x1C
|
||||||
|
#define EXT_CFG_IDDQ_BIAS (1 << 0)
|
||||||
|
#define EXT_CFG_PWR_DOWN (1 << 1)
|
||||||
|
#define EXT_CK25_DIS (1 << 4)
|
||||||
|
#define EXT_CFG_IDDQ_GLOBAL_PWR (1 << 3)
|
||||||
|
#define EXT_GPHY_RESET (1 << 5)
|
||||||
|
|
||||||
|
/* DMA rings size */
|
||||||
|
#define DMA_RING_SIZE (0x40)
|
||||||
|
#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DESC_INDEX + 1))
|
||||||
|
|
||||||
|
/* DMA registers common definitions */
|
||||||
|
#define DMA_RW_POINTER_MASK 0x1FF
|
||||||
|
#define DMA_P_INDEX_DISCARD_CNT_MASK 0xFFFF
|
||||||
|
#define DMA_P_INDEX_DISCARD_CNT_SHIFT 16
|
||||||
|
#define DMA_BUFFER_DONE_CNT_MASK 0xFFFF
|
||||||
|
#define DMA_BUFFER_DONE_CNT_SHIFT 16
|
||||||
|
#define DMA_P_INDEX_MASK 0xFFFF
|
||||||
|
#define DMA_C_INDEX_MASK 0xFFFF
|
||||||
|
|
||||||
|
/* DMA ring size register */
|
||||||
|
#define DMA_RING_SIZE_MASK 0xFFFF
|
||||||
|
#define DMA_RING_SIZE_SHIFT 16
|
||||||
|
#define DMA_RING_BUFFER_SIZE_MASK 0xFFFF
|
||||||
|
|
||||||
|
/* DMA interrupt threshold register */
|
||||||
|
#define DMA_INTR_THRESHOLD_MASK 0x01FF
|
||||||
|
|
||||||
|
/* DMA XON/XOFF register */
|
||||||
|
#define DMA_XON_THREHOLD_MASK 0xFFFF
|
||||||
|
#define DMA_XOFF_THRESHOLD_MASK 0xFFFF
|
||||||
|
#define DMA_XOFF_THRESHOLD_SHIFT 16
|
||||||
|
|
||||||
|
/* DMA flow period register */
|
||||||
|
#define DMA_FLOW_PERIOD_MASK 0xFFFF
|
||||||
|
#define DMA_MAX_PKT_SIZE_MASK 0xFFFF
|
||||||
|
#define DMA_MAX_PKT_SIZE_SHIFT 16
|
||||||
|
|
||||||
|
|
||||||
|
/* DMA control register */
|
||||||
|
#define DMA_EN (1 << 0)
|
||||||
|
#define DMA_RING_BUF_EN_SHIFT 0x01
|
||||||
|
#define DMA_RING_BUF_EN_MASK 0xFFFF
|
||||||
|
#define DMA_TSB_SWAP_EN (1 << 20)
|
||||||
|
|
||||||
|
/* DMA status register */
|
||||||
|
#define DMA_DISABLED (1 << 0)
|
||||||
|
#define DMA_DESC_RAM_INIT_BUSY (1 << 1)
|
||||||
|
|
||||||
|
/* DMA SCB burst size register */
|
||||||
|
#define DMA_SCB_BURST_SIZE_MASK 0x1F
|
||||||
|
|
||||||
|
/* DMA activity vector register */
|
||||||
|
#define DMA_ACTIVITY_VECTOR_MASK 0x1FFFF
|
||||||
|
|
||||||
|
/* DMA backpressure mask register */
|
||||||
|
#define DMA_BACKPRESSURE_MASK 0x1FFFF
|
||||||
|
#define DMA_PFC_ENABLE (1 << 31)
|
||||||
|
|
||||||
|
/* DMA backpressure status register */
|
||||||
|
#define DMA_BACKPRESSURE_STATUS_MASK 0x1FFFF
|
||||||
|
|
||||||
|
/* DMA override register */
|
||||||
|
#define DMA_LITTLE_ENDIAN_MODE (1 << 0)
|
||||||
|
#define DMA_REGISTER_MODE (1 << 1)
|
||||||
|
|
||||||
|
/* DMA timeout register */
|
||||||
|
#define DMA_TIMEOUT_MASK 0xFFFF
|
||||||
|
#define DMA_TIMEOUT_VAL 5000 /* micro seconds */
|
||||||
|
|
||||||
|
/* TDMA rate limiting control register */
|
||||||
|
#define DMA_RATE_LIMIT_EN_MASK 0xFFFF
|
||||||
|
|
||||||
|
/* TDMA arbitration control register */
|
||||||
|
#define DMA_ARBITER_MODE_MASK 0x03
|
||||||
|
#define DMA_RING_BUF_PRIORITY_MASK 0x1F
|
||||||
|
#define DMA_RING_BUF_PRIORITY_SHIFT 5
|
||||||
|
#define DMA_PRIO_REG_INDEX(q) ((q) / 6)
|
||||||
|
#define DMA_PRIO_REG_SHIFT(q) (((q) % 6) * DMA_RING_BUF_PRIORITY_SHIFT)
|
||||||
|
#define DMA_RATE_ADJ_MASK 0xFF
|
||||||
|
|
||||||
|
/* Tx/Rx Dma Descriptor common bits*/
|
||||||
|
#define DMA_BUFLENGTH_MASK 0x0fff
|
||||||
|
#define DMA_BUFLENGTH_SHIFT 16
|
||||||
|
#define DMA_OWN 0x8000
|
||||||
|
#define DMA_EOP 0x4000
|
||||||
|
#define DMA_SOP 0x2000
|
||||||
|
#define DMA_WRAP 0x1000
|
||||||
|
/* Tx specific Dma descriptor bits */
|
||||||
|
#define DMA_TX_UNDERRUN 0x0200
|
||||||
|
#define DMA_TX_APPEND_CRC 0x0040
|
||||||
|
#define DMA_TX_OW_CRC 0x0020
|
||||||
|
#define DMA_TX_DO_CSUM 0x0010
|
||||||
|
#define DMA_TX_QTAG_SHIFT 7
|
||||||
|
|
||||||
|
/* Rx Specific Dma descriptor bits */
|
||||||
|
#define DMA_RX_CHK_V3PLUS 0x8000
|
||||||
|
#define DMA_RX_CHK_V12 0x1000
|
||||||
|
#define DMA_RX_BRDCAST 0x0040
|
||||||
|
#define DMA_RX_MULT 0x0020
|
||||||
|
#define DMA_RX_LG 0x0010
|
||||||
|
#define DMA_RX_NO 0x0008
|
||||||
|
#define DMA_RX_RXER 0x0004
|
||||||
|
#define DMA_RX_CRC_ERROR 0x0002
|
||||||
|
#define DMA_RX_OV 0x0001
|
||||||
|
#define DMA_RX_FI_MASK 0x001F
|
||||||
|
#define DMA_RX_FI_SHIFT 0x0007
|
||||||
|
#define DMA_DESC_ALLOC_MASK 0x00FF
|
||||||
|
|
||||||
|
#define DMA_ARBITER_RR 0x00
|
||||||
|
#define DMA_ARBITER_WRR 0x01
|
||||||
|
#define DMA_ARBITER_SP 0x02
|
||||||
|
|
||||||
|
struct enet_cb {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
void __iomem *bd_addr;
|
||||||
|
DEFINE_DMA_UNMAP_ADDR(dma_addr);
|
||||||
|
DEFINE_DMA_UNMAP_LEN(dma_len);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* power management mode */
|
||||||
|
enum bcmgenet_power_mode {
|
||||||
|
GENET_POWER_CABLE_SENSE = 0,
|
||||||
|
GENET_POWER_PASSIVE,
|
||||||
|
GENET_POWER_WOL_MAGIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_priv;
|
||||||
|
|
||||||
|
/* We support both runtime GENET detection and compile-time
|
||||||
|
* to optimize code-paths for a given hardware
|
||||||
|
*/
|
||||||
|
enum bcmgenet_version {
|
||||||
|
GENET_V1 = 1,
|
||||||
|
GENET_V2,
|
||||||
|
GENET_V3,
|
||||||
|
GENET_V4,
|
||||||
|
GENET_V5
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GENET_IS_V1(p) ((p)->version == GENET_V1)
|
||||||
|
#define GENET_IS_V2(p) ((p)->version == GENET_V2)
|
||||||
|
#define GENET_IS_V3(p) ((p)->version == GENET_V3)
|
||||||
|
#define GENET_IS_V4(p) ((p)->version == GENET_V4)
|
||||||
|
#define GENET_IS_V5(p) ((p)->version == GENET_V5)
|
||||||
|
|
||||||
|
/* Hardware flags */
|
||||||
|
#define GENET_HAS_40BITS (1 << 0)
|
||||||
|
#define GENET_HAS_EXT (1 << 1)
|
||||||
|
#define GENET_HAS_MDIO_INTR (1 << 2)
|
||||||
|
#define GENET_HAS_MOCA_LINK_DET (1 << 3)
|
||||||
|
|
||||||
|
/* BCMGENET hardware parameters, keep this structure nicely aligned
|
||||||
|
* since it is going to be used in hot paths
|
||||||
|
*/
|
||||||
|
struct bcmgenet_hw_params {
|
||||||
|
u8 tx_queues;
|
||||||
|
u8 tx_bds_per_q;
|
||||||
|
u8 rx_queues;
|
||||||
|
u8 rx_bds_per_q;
|
||||||
|
u8 bp_in_en_shift;
|
||||||
|
u32 bp_in_mask;
|
||||||
|
u8 hfb_filter_cnt;
|
||||||
|
u8 hfb_filter_size;
|
||||||
|
u8 qtag_mask;
|
||||||
|
u16 tbuf_offset;
|
||||||
|
u32 hfb_offset;
|
||||||
|
u32 hfb_reg_offset;
|
||||||
|
u32 rdma_offset;
|
||||||
|
u32 tdma_offset;
|
||||||
|
u32 words_per_bd;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_skb_cb {
|
||||||
|
struct enet_cb *first_cb; /* First control block of SKB */
|
||||||
|
struct enet_cb *last_cb; /* Last control block of SKB */
|
||||||
|
unsigned int bytes_sent; /* bytes on the wire (no TSB) */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GENET_CB(skb) ((struct bcmgenet_skb_cb *)((skb)->cb))
|
||||||
|
|
||||||
|
struct bcmgenet_tx_ring {
|
||||||
|
spinlock_t lock; /* ring lock */
|
||||||
|
struct napi_struct napi; /* NAPI per tx queue */
|
||||||
|
unsigned long packets;
|
||||||
|
unsigned long bytes;
|
||||||
|
unsigned int index; /* ring index */
|
||||||
|
unsigned int queue; /* queue index */
|
||||||
|
struct enet_cb *cbs; /* tx ring buffer control block*/
|
||||||
|
unsigned int size; /* size of each tx ring */
|
||||||
|
unsigned int clean_ptr; /* Tx ring clean pointer */
|
||||||
|
unsigned int c_index; /* last consumer index of each ring*/
|
||||||
|
unsigned int free_bds; /* # of free bds for each ring */
|
||||||
|
unsigned int write_ptr; /* Tx ring write pointer SW copy */
|
||||||
|
unsigned int prod_index; /* Tx ring producer index SW copy */
|
||||||
|
unsigned int cb_ptr; /* Tx ring initial CB ptr */
|
||||||
|
unsigned int end_ptr; /* Tx ring end CB ptr */
|
||||||
|
void (*int_enable)(struct bcmgenet_tx_ring *);
|
||||||
|
void (*int_disable)(struct bcmgenet_tx_ring *);
|
||||||
|
struct bcmgenet_priv *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_net_dim {
|
||||||
|
u16 use_dim;
|
||||||
|
u16 event_ctr;
|
||||||
|
unsigned long packets;
|
||||||
|
unsigned long bytes;
|
||||||
|
struct dim dim;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_rx_ring {
|
||||||
|
struct napi_struct napi; /* Rx NAPI struct */
|
||||||
|
unsigned long bytes;
|
||||||
|
unsigned long packets;
|
||||||
|
unsigned long errors;
|
||||||
|
unsigned long dropped;
|
||||||
|
unsigned int index; /* Rx ring index */
|
||||||
|
struct enet_cb *cbs; /* Rx ring buffer control block */
|
||||||
|
unsigned int size; /* Rx ring size */
|
||||||
|
unsigned int c_index; /* Rx last consumer index */
|
||||||
|
unsigned int read_ptr; /* Rx ring read pointer */
|
||||||
|
unsigned int cb_ptr; /* Rx ring initial CB ptr */
|
||||||
|
unsigned int end_ptr; /* Rx ring end CB ptr */
|
||||||
|
unsigned int old_discards;
|
||||||
|
struct bcmgenet_net_dim dim;
|
||||||
|
u32 rx_max_coalesced_frames;
|
||||||
|
u32 rx_coalesce_usecs;
|
||||||
|
void (*int_enable)(struct bcmgenet_rx_ring *);
|
||||||
|
void (*int_disable)(struct bcmgenet_rx_ring *);
|
||||||
|
struct bcmgenet_priv *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum bcmgenet_rxnfc_state {
|
||||||
|
BCMGENET_RXNFC_STATE_UNUSED = 0,
|
||||||
|
BCMGENET_RXNFC_STATE_DISABLED,
|
||||||
|
BCMGENET_RXNFC_STATE_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_rxnfc_rule {
|
||||||
|
struct list_head list;
|
||||||
|
struct ethtool_rx_flow_spec fs;
|
||||||
|
enum bcmgenet_rxnfc_state state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* device context */
|
||||||
|
struct bcmgenet_priv {
|
||||||
|
void __iomem *base;
|
||||||
|
enum bcmgenet_version version;
|
||||||
|
struct net_device *dev;
|
||||||
|
|
||||||
|
/* transmit variables */
|
||||||
|
void __iomem *tx_bds;
|
||||||
|
struct enet_cb *tx_cbs;
|
||||||
|
unsigned int num_tx_bds;
|
||||||
|
|
||||||
|
struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
|
||||||
|
|
||||||
|
/* receive variables */
|
||||||
|
void __iomem *rx_bds;
|
||||||
|
struct enet_cb *rx_cbs;
|
||||||
|
unsigned int num_rx_bds;
|
||||||
|
unsigned int rx_buf_len;
|
||||||
|
struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
|
||||||
|
struct list_head rxnfc_list;
|
||||||
|
|
||||||
|
struct bcmgenet_rx_ring rx_rings[DESC_INDEX + 1];
|
||||||
|
|
||||||
|
/* other misc variables */
|
||||||
|
struct bcmgenet_hw_params *hw_params;
|
||||||
|
unsigned autoneg_pause:1;
|
||||||
|
unsigned tx_pause:1;
|
||||||
|
unsigned rx_pause:1;
|
||||||
|
|
||||||
|
/* MDIO bus variables */
|
||||||
|
wait_queue_head_t wq;
|
||||||
|
bool internal_phy;
|
||||||
|
struct device_node *phy_dn;
|
||||||
|
struct device_node *mdio_dn;
|
||||||
|
struct mii_bus *mii_bus;
|
||||||
|
u16 gphy_rev;
|
||||||
|
struct clk *clk_eee;
|
||||||
|
bool clk_eee_enabled;
|
||||||
|
|
||||||
|
/* PHY device variables */
|
||||||
|
phy_interface_t phy_interface;
|
||||||
|
int phy_addr;
|
||||||
|
int ext_phy;
|
||||||
|
bool ephy_16nm;
|
||||||
|
|
||||||
|
/* Interrupt variables */
|
||||||
|
struct work_struct bcmgenet_irq_work;
|
||||||
|
int irq0;
|
||||||
|
int irq1;
|
||||||
|
int wol_irq;
|
||||||
|
bool wol_irq_disabled;
|
||||||
|
|
||||||
|
/* shared status */
|
||||||
|
spinlock_t lock;
|
||||||
|
unsigned int irq0_stat;
|
||||||
|
|
||||||
|
/* HW descriptors/checksum variables */
|
||||||
|
bool crc_fwd_en;
|
||||||
|
|
||||||
|
u32 dma_max_burst_length;
|
||||||
|
|
||||||
|
u32 msg_enable;
|
||||||
|
|
||||||
|
struct clk *clk;
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct platform_device *mii_pdev;
|
||||||
|
|
||||||
|
/* WOL */
|
||||||
|
struct clk *clk_wol;
|
||||||
|
u32 wolopts;
|
||||||
|
u8 sopass[SOPASS_MAX];
|
||||||
|
bool wol_active;
|
||||||
|
|
||||||
|
struct bcmgenet_mib_counters mib;
|
||||||
|
|
||||||
|
struct ethtool_eee eee;
|
||||||
|
/* EtherCAT device variables */
|
||||||
|
ec_device_t *ecdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GENET_IO_MACRO(name, offset) \
|
||||||
|
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
|
||||||
|
u32 off) \
|
||||||
|
{ \
|
||||||
|
/* MIPS chips strapped for BE will automagically configure the \
|
||||||
|
* peripheral registers for CPU-native byte order. \
|
||||||
|
*/ \
|
||||||
|
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||||
|
return __raw_readl(priv->base + offset + off); \
|
||||||
|
else \
|
||||||
|
return readl_relaxed(priv->base + offset + off); \
|
||||||
|
} \
|
||||||
|
static inline void bcmgenet_##name##_writel(struct bcmgenet_priv *priv, \
|
||||||
|
u32 val, u32 off) \
|
||||||
|
{ \
|
||||||
|
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||||
|
__raw_writel(val, priv->base + offset + off); \
|
||||||
|
else \
|
||||||
|
writel_relaxed(val, priv->base + offset + off); \
|
||||||
|
}
|
||||||
|
|
||||||
|
GENET_IO_MACRO(ext, GENET_EXT_OFF);
|
||||||
|
GENET_IO_MACRO(umac, GENET_UMAC_OFF);
|
||||||
|
GENET_IO_MACRO(sys, GENET_SYS_OFF);
|
||||||
|
|
||||||
|
/* interrupt l2 registers accessors */
|
||||||
|
GENET_IO_MACRO(intrl2_0, GENET_INTRL2_0_OFF);
|
||||||
|
GENET_IO_MACRO(intrl2_1, GENET_INTRL2_1_OFF);
|
||||||
|
|
||||||
|
/* HFB register accessors */
|
||||||
|
GENET_IO_MACRO(hfb, priv->hw_params->hfb_offset);
|
||||||
|
|
||||||
|
/* GENET v2+ HFB control and filter len helpers */
|
||||||
|
GENET_IO_MACRO(hfb_reg, priv->hw_params->hfb_reg_offset);
|
||||||
|
|
||||||
|
/* RBUF register accessors */
|
||||||
|
GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
|
||||||
|
|
||||||
|
/* MDIO routines */
|
||||||
|
int bcmgenet_mii_init(struct net_device *dev);
|
||||||
|
int bcmgenet_mii_config(struct net_device *dev, bool init);
|
||||||
|
int bcmgenet_mii_probe(struct net_device *dev);
|
||||||
|
void bcmgenet_mii_exit(struct net_device *dev);
|
||||||
|
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx);
|
||||||
|
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
|
||||||
|
void bcmgenet_mii_setup(struct net_device *dev);
|
||||||
|
|
||||||
|
/* Wake-on-LAN routines */
|
||||||
|
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||||
|
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||||
|
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode);
|
||||||
|
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode);
|
||||||
|
|
||||||
|
void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
|
||||||
|
bool tx_lpi_enabled);
|
||||||
|
|
||||||
|
#endif /* __BCMGENET_H__ */
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,709 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2020 Broadcom
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BCMGENET_H__
|
||||||
|
#define __BCMGENET_H__
|
||||||
|
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/dim.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
|
||||||
|
#include "../unimac.h"
|
||||||
|
|
||||||
|
/* total number of Buffer Descriptors, same for Rx/Tx */
|
||||||
|
#define TOTAL_DESC 256
|
||||||
|
|
||||||
|
/* which ring is descriptor based */
|
||||||
|
#define DESC_INDEX 16
|
||||||
|
|
||||||
|
/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
|
||||||
|
* 1536 is multiple of 256 bytes
|
||||||
|
*/
|
||||||
|
#define ENET_BRCM_TAG_LEN 6
|
||||||
|
#define ENET_PAD 8
|
||||||
|
#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
|
||||||
|
ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
|
||||||
|
#define DMA_MAX_BURST_LENGTH 0x10
|
||||||
|
|
||||||
|
/* misc. configuration */
|
||||||
|
#define MAX_NUM_OF_FS_RULES 16
|
||||||
|
#define CLEAR_ALL_HFB 0xFF
|
||||||
|
#define DMA_FC_THRESH_HI (TOTAL_DESC >> 4)
|
||||||
|
#define DMA_FC_THRESH_LO 5
|
||||||
|
|
||||||
|
/* 64B receive/transmit status block */
|
||||||
|
struct status_64 {
|
||||||
|
u32 length_status; /* length and peripheral status */
|
||||||
|
u32 ext_status; /* Extended status*/
|
||||||
|
u32 rx_csum; /* partial rx checksum */
|
||||||
|
u32 unused1[9]; /* unused */
|
||||||
|
u32 tx_csum_info; /* Tx checksum info. */
|
||||||
|
u32 unused2[3]; /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Rx status bits */
|
||||||
|
#define STATUS_RX_EXT_MASK 0x1FFFFF
|
||||||
|
#define STATUS_RX_CSUM_MASK 0xFFFF
|
||||||
|
#define STATUS_RX_CSUM_OK 0x10000
|
||||||
|
#define STATUS_RX_CSUM_FR 0x20000
|
||||||
|
#define STATUS_RX_PROTO_TCP 0
|
||||||
|
#define STATUS_RX_PROTO_UDP 1
|
||||||
|
#define STATUS_RX_PROTO_ICMP 2
|
||||||
|
#define STATUS_RX_PROTO_OTHER 3
|
||||||
|
#define STATUS_RX_PROTO_MASK 3
|
||||||
|
#define STATUS_RX_PROTO_SHIFT 18
|
||||||
|
#define STATUS_FILTER_INDEX_MASK 0xFFFF
|
||||||
|
/* Tx status bits */
|
||||||
|
#define STATUS_TX_CSUM_START_MASK 0X7FFF
|
||||||
|
#define STATUS_TX_CSUM_START_SHIFT 16
|
||||||
|
#define STATUS_TX_CSUM_PROTO_UDP 0x8000
|
||||||
|
#define STATUS_TX_CSUM_OFFSET_MASK 0x7FFF
|
||||||
|
#define STATUS_TX_CSUM_LV 0x80000000
|
||||||
|
|
||||||
|
/* DMA Descriptor */
|
||||||
|
#define DMA_DESC_LENGTH_STATUS 0x00 /* in bytes of data in buffer */
|
||||||
|
#define DMA_DESC_ADDRESS_LO 0x04 /* lower bits of PA */
|
||||||
|
#define DMA_DESC_ADDRESS_HI 0x08 /* upper 32 bits of PA, GENETv4+ */
|
||||||
|
|
||||||
|
/* Rx/Tx common counter group */
|
||||||
|
struct bcmgenet_pkt_counters {
|
||||||
|
u32 cnt_64; /* RO Received/Transmited 64 bytes packet */
|
||||||
|
u32 cnt_127; /* RO Rx/Tx 127 bytes packet */
|
||||||
|
u32 cnt_255; /* RO Rx/Tx 65-255 bytes packet */
|
||||||
|
u32 cnt_511; /* RO Rx/Tx 256-511 bytes packet */
|
||||||
|
u32 cnt_1023; /* RO Rx/Tx 512-1023 bytes packet */
|
||||||
|
u32 cnt_1518; /* RO Rx/Tx 1024-1518 bytes packet */
|
||||||
|
u32 cnt_mgv; /* RO Rx/Tx 1519-1522 good VLAN packet */
|
||||||
|
u32 cnt_2047; /* RO Rx/Tx 1522-2047 bytes packet*/
|
||||||
|
u32 cnt_4095; /* RO Rx/Tx 2048-4095 bytes packet*/
|
||||||
|
u32 cnt_9216; /* RO Rx/Tx 4096-9216 bytes packet*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/* RSV, Receive Status Vector */
|
||||||
|
struct bcmgenet_rx_counters {
|
||||||
|
struct bcmgenet_pkt_counters pkt_cnt;
|
||||||
|
u32 pkt; /* RO (0x428) Received pkt count*/
|
||||||
|
u32 bytes; /* RO Received byte count */
|
||||||
|
u32 mca; /* RO # of Received multicast pkt */
|
||||||
|
u32 bca; /* RO # of Receive broadcast pkt */
|
||||||
|
u32 fcs; /* RO # of Received FCS error */
|
||||||
|
u32 cf; /* RO # of Received control frame pkt*/
|
||||||
|
u32 pf; /* RO # of Received pause frame pkt */
|
||||||
|
u32 uo; /* RO # of unknown op code pkt */
|
||||||
|
u32 aln; /* RO # of alignment error count */
|
||||||
|
u32 flr; /* RO # of frame length out of range count */
|
||||||
|
u32 cde; /* RO # of code error pkt */
|
||||||
|
u32 fcr; /* RO # of carrier sense error pkt */
|
||||||
|
u32 ovr; /* RO # of oversize pkt*/
|
||||||
|
u32 jbr; /* RO # of jabber count */
|
||||||
|
u32 mtue; /* RO # of MTU error pkt*/
|
||||||
|
u32 pok; /* RO # of Received good pkt */
|
||||||
|
u32 uc; /* RO # of unicast pkt */
|
||||||
|
u32 ppp; /* RO # of PPP pkt */
|
||||||
|
u32 rcrc; /* RO (0x470),# of CRC match pkt */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TSV, Transmit Status Vector */
|
||||||
|
struct bcmgenet_tx_counters {
|
||||||
|
struct bcmgenet_pkt_counters pkt_cnt;
|
||||||
|
u32 pkts; /* RO (0x4a8) Transmited pkt */
|
||||||
|
u32 mca; /* RO # of xmited multicast pkt */
|
||||||
|
u32 bca; /* RO # of xmited broadcast pkt */
|
||||||
|
u32 pf; /* RO # of xmited pause frame count */
|
||||||
|
u32 cf; /* RO # of xmited control frame count */
|
||||||
|
u32 fcs; /* RO # of xmited FCS error count */
|
||||||
|
u32 ovr; /* RO # of xmited oversize pkt */
|
||||||
|
u32 drf; /* RO # of xmited deferral pkt */
|
||||||
|
u32 edf; /* RO # of xmited Excessive deferral pkt*/
|
||||||
|
u32 scl; /* RO # of xmited single collision pkt */
|
||||||
|
u32 mcl; /* RO # of xmited multiple collision pkt*/
|
||||||
|
u32 lcl; /* RO # of xmited late collision pkt */
|
||||||
|
u32 ecl; /* RO # of xmited excessive collision pkt*/
|
||||||
|
u32 frg; /* RO # of xmited fragments pkt*/
|
||||||
|
u32 ncl; /* RO # of xmited total collision count */
|
||||||
|
u32 jbr; /* RO # of xmited jabber count*/
|
||||||
|
u32 bytes; /* RO # of xmited byte count */
|
||||||
|
u32 pok; /* RO # of xmited good pkt */
|
||||||
|
u32 uc; /* RO (0x0x4f0)# of xmited unitcast pkt */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_mib_counters {
|
||||||
|
struct bcmgenet_rx_counters rx;
|
||||||
|
struct bcmgenet_tx_counters tx;
|
||||||
|
u32 rx_runt_cnt;
|
||||||
|
u32 rx_runt_fcs;
|
||||||
|
u32 rx_runt_fcs_align;
|
||||||
|
u32 rx_runt_bytes;
|
||||||
|
u32 rbuf_ovflow_cnt;
|
||||||
|
u32 rbuf_err_cnt;
|
||||||
|
u32 mdf_err_cnt;
|
||||||
|
u32 alloc_rx_buff_failed;
|
||||||
|
u32 rx_dma_failed;
|
||||||
|
u32 tx_dma_failed;
|
||||||
|
u32 tx_realloc_tsb;
|
||||||
|
u32 tx_realloc_tsb_failed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UMAC_MIB_START 0x400
|
||||||
|
|
||||||
|
#define UMAC_MDIO_CMD 0x614
|
||||||
|
#define MDIO_START_BUSY (1 << 29)
|
||||||
|
#define MDIO_READ_FAIL (1 << 28)
|
||||||
|
#define MDIO_RD (2 << 26)
|
||||||
|
#define MDIO_WR (1 << 26)
|
||||||
|
#define MDIO_PMD_SHIFT 21
|
||||||
|
#define MDIO_PMD_MASK 0x1F
|
||||||
|
#define MDIO_REG_SHIFT 16
|
||||||
|
#define MDIO_REG_MASK 0x1F
|
||||||
|
|
||||||
|
#define UMAC_RBUF_OVFL_CNT_V1 0x61C
|
||||||
|
#define RBUF_OVFL_CNT_V2 0x80
|
||||||
|
#define RBUF_OVFL_CNT_V3PLUS 0x94
|
||||||
|
|
||||||
|
#define UMAC_MPD_CTRL 0x620
|
||||||
|
#define MPD_EN (1 << 0)
|
||||||
|
#define MPD_PW_EN (1 << 27)
|
||||||
|
#define MPD_MSEQ_LEN_SHIFT 16
|
||||||
|
#define MPD_MSEQ_LEN_MASK 0xFF
|
||||||
|
|
||||||
|
#define UMAC_MPD_PW_MS 0x624
|
||||||
|
#define UMAC_MPD_PW_LS 0x628
|
||||||
|
#define UMAC_RBUF_ERR_CNT_V1 0x634
|
||||||
|
#define RBUF_ERR_CNT_V2 0x84
|
||||||
|
#define RBUF_ERR_CNT_V3PLUS 0x98
|
||||||
|
#define UMAC_MDF_ERR_CNT 0x638
|
||||||
|
#define UMAC_MDF_CTRL 0x650
|
||||||
|
#define UMAC_MDF_ADDR 0x654
|
||||||
|
#define UMAC_MIB_CTRL 0x580
|
||||||
|
#define MIB_RESET_RX (1 << 0)
|
||||||
|
#define MIB_RESET_RUNT (1 << 1)
|
||||||
|
#define MIB_RESET_TX (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_CTRL 0x00
|
||||||
|
#define RBUF_64B_EN (1 << 0)
|
||||||
|
#define RBUF_ALIGN_2B (1 << 1)
|
||||||
|
#define RBUF_BAD_DIS (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_STATUS 0x0C
|
||||||
|
#define RBUF_STATUS_WOL (1 << 0)
|
||||||
|
#define RBUF_STATUS_MPD_INTR_ACTIVE (1 << 1)
|
||||||
|
#define RBUF_STATUS_ACPI_INTR_ACTIVE (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_CHK_CTRL 0x14
|
||||||
|
#define RBUF_RXCHK_EN (1 << 0)
|
||||||
|
#define RBUF_SKIP_FCS (1 << 4)
|
||||||
|
#define RBUF_L3_PARSE_DIS (1 << 5)
|
||||||
|
|
||||||
|
#define RBUF_ENERGY_CTRL 0x9c
|
||||||
|
#define RBUF_EEE_EN (1 << 0)
|
||||||
|
#define RBUF_PM_EN (1 << 1)
|
||||||
|
|
||||||
|
#define RBUF_TBUF_SIZE_CTRL 0xb4
|
||||||
|
|
||||||
|
#define RBUF_HFB_CTRL_V1 0x38
|
||||||
|
#define RBUF_HFB_FILTER_EN_SHIFT 16
|
||||||
|
#define RBUF_HFB_FILTER_EN_MASK 0xffff0000
|
||||||
|
#define RBUF_HFB_EN (1 << 0)
|
||||||
|
#define RBUF_HFB_256B (1 << 1)
|
||||||
|
#define RBUF_ACPI_EN (1 << 2)
|
||||||
|
|
||||||
|
#define RBUF_HFB_LEN_V1 0x3C
|
||||||
|
#define RBUF_FLTR_LEN_MASK 0xFF
|
||||||
|
#define RBUF_FLTR_LEN_SHIFT 8
|
||||||
|
|
||||||
|
#define TBUF_CTRL 0x00
|
||||||
|
#define TBUF_64B_EN (1 << 0)
|
||||||
|
#define TBUF_BP_MC 0x0C
|
||||||
|
#define TBUF_ENERGY_CTRL 0x14
|
||||||
|
#define TBUF_EEE_EN (1 << 0)
|
||||||
|
#define TBUF_PM_EN (1 << 1)
|
||||||
|
|
||||||
|
#define TBUF_CTRL_V1 0x80
|
||||||
|
#define TBUF_BP_MC_V1 0xA0
|
||||||
|
|
||||||
|
#define HFB_CTRL 0x00
|
||||||
|
#define HFB_FLT_ENABLE_V3PLUS 0x04
|
||||||
|
#define HFB_FLT_LEN_V2 0x04
|
||||||
|
#define HFB_FLT_LEN_V3PLUS 0x1C
|
||||||
|
|
||||||
|
/* uniMac intrl2 registers */
|
||||||
|
#define INTRL2_CPU_STAT 0x00
|
||||||
|
#define INTRL2_CPU_SET 0x04
|
||||||
|
#define INTRL2_CPU_CLEAR 0x08
|
||||||
|
#define INTRL2_CPU_MASK_STATUS 0x0C
|
||||||
|
#define INTRL2_CPU_MASK_SET 0x10
|
||||||
|
#define INTRL2_CPU_MASK_CLEAR 0x14
|
||||||
|
|
||||||
|
/* INTRL2 instance 0 definitions */
|
||||||
|
#define UMAC_IRQ_SCB (1 << 0)
|
||||||
|
#define UMAC_IRQ_EPHY (1 << 1)
|
||||||
|
#define UMAC_IRQ_PHY_DET_R (1 << 2)
|
||||||
|
#define UMAC_IRQ_PHY_DET_F (1 << 3)
|
||||||
|
#define UMAC_IRQ_LINK_UP (1 << 4)
|
||||||
|
#define UMAC_IRQ_LINK_DOWN (1 << 5)
|
||||||
|
#define UMAC_IRQ_LINK_EVENT (UMAC_IRQ_LINK_UP | UMAC_IRQ_LINK_DOWN)
|
||||||
|
#define UMAC_IRQ_UMAC (1 << 6)
|
||||||
|
#define UMAC_IRQ_UMAC_TSV (1 << 7)
|
||||||
|
#define UMAC_IRQ_TBUF_UNDERRUN (1 << 8)
|
||||||
|
#define UMAC_IRQ_RBUF_OVERFLOW (1 << 9)
|
||||||
|
#define UMAC_IRQ_HFB_SM (1 << 10)
|
||||||
|
#define UMAC_IRQ_HFB_MM (1 << 11)
|
||||||
|
#define UMAC_IRQ_MPD_R (1 << 12)
|
||||||
|
#define UMAC_IRQ_WAKE_EVENT (UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM | \
|
||||||
|
UMAC_IRQ_MPD_R)
|
||||||
|
#define UMAC_IRQ_RXDMA_MBDONE (1 << 13)
|
||||||
|
#define UMAC_IRQ_RXDMA_PDONE (1 << 14)
|
||||||
|
#define UMAC_IRQ_RXDMA_BDONE (1 << 15)
|
||||||
|
#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
|
||||||
|
#define UMAC_IRQ_TXDMA_MBDONE (1 << 16)
|
||||||
|
#define UMAC_IRQ_TXDMA_PDONE (1 << 17)
|
||||||
|
#define UMAC_IRQ_TXDMA_BDONE (1 << 18)
|
||||||
|
#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
|
||||||
|
|
||||||
|
/* Only valid for GENETv3+ */
|
||||||
|
#define UMAC_IRQ_MDIO_DONE (1 << 23)
|
||||||
|
#define UMAC_IRQ_MDIO_ERROR (1 << 24)
|
||||||
|
|
||||||
|
/* INTRL2 instance 1 definitions */
|
||||||
|
#define UMAC_IRQ1_TX_INTR_MASK 0xFFFF
|
||||||
|
#define UMAC_IRQ1_RX_INTR_MASK 0xFFFF
|
||||||
|
#define UMAC_IRQ1_RX_INTR_SHIFT 16
|
||||||
|
|
||||||
|
/* Register block offsets */
|
||||||
|
#define GENET_SYS_OFF 0x0000
|
||||||
|
#define GENET_GR_BRIDGE_OFF 0x0040
|
||||||
|
#define GENET_EXT_OFF 0x0080
|
||||||
|
#define GENET_INTRL2_0_OFF 0x0200
|
||||||
|
#define GENET_INTRL2_1_OFF 0x0240
|
||||||
|
#define GENET_RBUF_OFF 0x0300
|
||||||
|
#define GENET_UMAC_OFF 0x0800
|
||||||
|
|
||||||
|
/* SYS block offsets and register definitions */
|
||||||
|
#define SYS_REV_CTRL 0x00
|
||||||
|
#define SYS_PORT_CTRL 0x04
|
||||||
|
#define PORT_MODE_INT_EPHY 0
|
||||||
|
#define PORT_MODE_INT_GPHY 1
|
||||||
|
#define PORT_MODE_EXT_EPHY 2
|
||||||
|
#define PORT_MODE_EXT_GPHY 3
|
||||||
|
#define PORT_MODE_EXT_RVMII_25 (4 | BIT(4))
|
||||||
|
#define PORT_MODE_EXT_RVMII_50 4
|
||||||
|
#define LED_ACT_SOURCE_MAC (1 << 9)
|
||||||
|
|
||||||
|
#define SYS_RBUF_FLUSH_CTRL 0x08
|
||||||
|
#define SYS_TBUF_FLUSH_CTRL 0x0C
|
||||||
|
#define RBUF_FLUSH_CTRL_V1 0x04
|
||||||
|
|
||||||
|
/* Ext block register offsets and definitions */
|
||||||
|
#define EXT_EXT_PWR_MGMT 0x00
|
||||||
|
#define EXT_PWR_DOWN_BIAS (1 << 0)
|
||||||
|
#define EXT_PWR_DOWN_DLL (1 << 1)
|
||||||
|
#define EXT_PWR_DOWN_PHY (1 << 2)
|
||||||
|
#define EXT_PWR_DN_EN_LD (1 << 3)
|
||||||
|
#define EXT_ENERGY_DET (1 << 4)
|
||||||
|
#define EXT_IDDQ_FROM_PHY (1 << 5)
|
||||||
|
#define EXT_IDDQ_GLBL_PWR (1 << 7)
|
||||||
|
#define EXT_PHY_RESET (1 << 8)
|
||||||
|
#define EXT_ENERGY_DET_MASK (1 << 12)
|
||||||
|
#define EXT_PWR_DOWN_PHY_TX (1 << 16)
|
||||||
|
#define EXT_PWR_DOWN_PHY_RX (1 << 17)
|
||||||
|
#define EXT_PWR_DOWN_PHY_SD (1 << 18)
|
||||||
|
#define EXT_PWR_DOWN_PHY_RD (1 << 19)
|
||||||
|
#define EXT_PWR_DOWN_PHY_EN (1 << 20)
|
||||||
|
|
||||||
|
#define EXT_RGMII_OOB_CTRL 0x0C
|
||||||
|
#define RGMII_MODE_EN_V123 (1 << 0)
|
||||||
|
#define RGMII_LINK (1 << 4)
|
||||||
|
#define OOB_DISABLE (1 << 5)
|
||||||
|
#define RGMII_MODE_EN (1 << 6)
|
||||||
|
#define ID_MODE_DIS (1 << 16)
|
||||||
|
|
||||||
|
#define EXT_GPHY_CTRL 0x1C
|
||||||
|
#define EXT_CFG_IDDQ_BIAS (1 << 0)
|
||||||
|
#define EXT_CFG_PWR_DOWN (1 << 1)
|
||||||
|
#define EXT_CK25_DIS (1 << 4)
|
||||||
|
#define EXT_CFG_IDDQ_GLOBAL_PWR (1 << 3)
|
||||||
|
#define EXT_GPHY_RESET (1 << 5)
|
||||||
|
|
||||||
|
/* DMA rings size */
|
||||||
|
#define DMA_RING_SIZE (0x40)
|
||||||
|
#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DESC_INDEX + 1))
|
||||||
|
|
||||||
|
/* DMA registers common definitions */
|
||||||
|
#define DMA_RW_POINTER_MASK 0x1FF
|
||||||
|
#define DMA_P_INDEX_DISCARD_CNT_MASK 0xFFFF
|
||||||
|
#define DMA_P_INDEX_DISCARD_CNT_SHIFT 16
|
||||||
|
#define DMA_BUFFER_DONE_CNT_MASK 0xFFFF
|
||||||
|
#define DMA_BUFFER_DONE_CNT_SHIFT 16
|
||||||
|
#define DMA_P_INDEX_MASK 0xFFFF
|
||||||
|
#define DMA_C_INDEX_MASK 0xFFFF
|
||||||
|
|
||||||
|
/* DMA ring size register */
|
||||||
|
#define DMA_RING_SIZE_MASK 0xFFFF
|
||||||
|
#define DMA_RING_SIZE_SHIFT 16
|
||||||
|
#define DMA_RING_BUFFER_SIZE_MASK 0xFFFF
|
||||||
|
|
||||||
|
/* DMA interrupt threshold register */
|
||||||
|
#define DMA_INTR_THRESHOLD_MASK 0x01FF
|
||||||
|
|
||||||
|
/* DMA XON/XOFF register */
|
||||||
|
#define DMA_XON_THREHOLD_MASK 0xFFFF
|
||||||
|
#define DMA_XOFF_THRESHOLD_MASK 0xFFFF
|
||||||
|
#define DMA_XOFF_THRESHOLD_SHIFT 16
|
||||||
|
|
||||||
|
/* DMA flow period register */
|
||||||
|
#define DMA_FLOW_PERIOD_MASK 0xFFFF
|
||||||
|
#define DMA_MAX_PKT_SIZE_MASK 0xFFFF
|
||||||
|
#define DMA_MAX_PKT_SIZE_SHIFT 16
|
||||||
|
|
||||||
|
|
||||||
|
/* DMA control register */
|
||||||
|
#define DMA_EN (1 << 0)
|
||||||
|
#define DMA_RING_BUF_EN_SHIFT 0x01
|
||||||
|
#define DMA_RING_BUF_EN_MASK 0xFFFF
|
||||||
|
#define DMA_TSB_SWAP_EN (1 << 20)
|
||||||
|
|
||||||
|
/* DMA status register */
|
||||||
|
#define DMA_DISABLED (1 << 0)
|
||||||
|
#define DMA_DESC_RAM_INIT_BUSY (1 << 1)
|
||||||
|
|
||||||
|
/* DMA SCB burst size register */
|
||||||
|
#define DMA_SCB_BURST_SIZE_MASK 0x1F
|
||||||
|
|
||||||
|
/* DMA activity vector register */
|
||||||
|
#define DMA_ACTIVITY_VECTOR_MASK 0x1FFFF
|
||||||
|
|
||||||
|
/* DMA backpressure mask register */
|
||||||
|
#define DMA_BACKPRESSURE_MASK 0x1FFFF
|
||||||
|
#define DMA_PFC_ENABLE (1 << 31)
|
||||||
|
|
||||||
|
/* DMA backpressure status register */
|
||||||
|
#define DMA_BACKPRESSURE_STATUS_MASK 0x1FFFF
|
||||||
|
|
||||||
|
/* DMA override register */
|
||||||
|
#define DMA_LITTLE_ENDIAN_MODE (1 << 0)
|
||||||
|
#define DMA_REGISTER_MODE (1 << 1)
|
||||||
|
|
||||||
|
/* DMA timeout register */
|
||||||
|
#define DMA_TIMEOUT_MASK 0xFFFF
|
||||||
|
#define DMA_TIMEOUT_VAL 5000 /* micro seconds */
|
||||||
|
|
||||||
|
/* TDMA rate limiting control register */
|
||||||
|
#define DMA_RATE_LIMIT_EN_MASK 0xFFFF
|
||||||
|
|
||||||
|
/* TDMA arbitration control register */
|
||||||
|
#define DMA_ARBITER_MODE_MASK 0x03
|
||||||
|
#define DMA_RING_BUF_PRIORITY_MASK 0x1F
|
||||||
|
#define DMA_RING_BUF_PRIORITY_SHIFT 5
|
||||||
|
#define DMA_PRIO_REG_INDEX(q) ((q) / 6)
|
||||||
|
#define DMA_PRIO_REG_SHIFT(q) (((q) % 6) * DMA_RING_BUF_PRIORITY_SHIFT)
|
||||||
|
#define DMA_RATE_ADJ_MASK 0xFF
|
||||||
|
|
||||||
|
/* Tx/Rx Dma Descriptor common bits*/
|
||||||
|
#define DMA_BUFLENGTH_MASK 0x0fff
|
||||||
|
#define DMA_BUFLENGTH_SHIFT 16
|
||||||
|
#define DMA_OWN 0x8000
|
||||||
|
#define DMA_EOP 0x4000
|
||||||
|
#define DMA_SOP 0x2000
|
||||||
|
#define DMA_WRAP 0x1000
|
||||||
|
/* Tx specific Dma descriptor bits */
|
||||||
|
#define DMA_TX_UNDERRUN 0x0200
|
||||||
|
#define DMA_TX_APPEND_CRC 0x0040
|
||||||
|
#define DMA_TX_OW_CRC 0x0020
|
||||||
|
#define DMA_TX_DO_CSUM 0x0010
|
||||||
|
#define DMA_TX_QTAG_SHIFT 7
|
||||||
|
|
||||||
|
/* Rx Specific Dma descriptor bits */
|
||||||
|
#define DMA_RX_CHK_V3PLUS 0x8000
|
||||||
|
#define DMA_RX_CHK_V12 0x1000
|
||||||
|
#define DMA_RX_BRDCAST 0x0040
|
||||||
|
#define DMA_RX_MULT 0x0020
|
||||||
|
#define DMA_RX_LG 0x0010
|
||||||
|
#define DMA_RX_NO 0x0008
|
||||||
|
#define DMA_RX_RXER 0x0004
|
||||||
|
#define DMA_RX_CRC_ERROR 0x0002
|
||||||
|
#define DMA_RX_OV 0x0001
|
||||||
|
#define DMA_RX_FI_MASK 0x001F
|
||||||
|
#define DMA_RX_FI_SHIFT 0x0007
|
||||||
|
#define DMA_DESC_ALLOC_MASK 0x00FF
|
||||||
|
|
||||||
|
#define DMA_ARBITER_RR 0x00
|
||||||
|
#define DMA_ARBITER_WRR 0x01
|
||||||
|
#define DMA_ARBITER_SP 0x02
|
||||||
|
|
||||||
|
struct enet_cb {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
void __iomem *bd_addr;
|
||||||
|
DEFINE_DMA_UNMAP_ADDR(dma_addr);
|
||||||
|
DEFINE_DMA_UNMAP_LEN(dma_len);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* power management mode */
|
||||||
|
enum bcmgenet_power_mode {
|
||||||
|
GENET_POWER_CABLE_SENSE = 0,
|
||||||
|
GENET_POWER_PASSIVE,
|
||||||
|
GENET_POWER_WOL_MAGIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_priv;
|
||||||
|
|
||||||
|
/* We support both runtime GENET detection and compile-time
|
||||||
|
* to optimize code-paths for a given hardware
|
||||||
|
*/
|
||||||
|
enum bcmgenet_version {
|
||||||
|
GENET_V1 = 1,
|
||||||
|
GENET_V2,
|
||||||
|
GENET_V3,
|
||||||
|
GENET_V4,
|
||||||
|
GENET_V5
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GENET_IS_V1(p) ((p)->version == GENET_V1)
|
||||||
|
#define GENET_IS_V2(p) ((p)->version == GENET_V2)
|
||||||
|
#define GENET_IS_V3(p) ((p)->version == GENET_V3)
|
||||||
|
#define GENET_IS_V4(p) ((p)->version == GENET_V4)
|
||||||
|
#define GENET_IS_V5(p) ((p)->version == GENET_V5)
|
||||||
|
|
||||||
|
/* Hardware flags */
|
||||||
|
#define GENET_HAS_40BITS (1 << 0)
|
||||||
|
#define GENET_HAS_EXT (1 << 1)
|
||||||
|
#define GENET_HAS_MDIO_INTR (1 << 2)
|
||||||
|
#define GENET_HAS_MOCA_LINK_DET (1 << 3)
|
||||||
|
|
||||||
|
/* BCMGENET hardware parameters, keep this structure nicely aligned
|
||||||
|
* since it is going to be used in hot paths
|
||||||
|
*/
|
||||||
|
struct bcmgenet_hw_params {
|
||||||
|
u8 tx_queues;
|
||||||
|
u8 tx_bds_per_q;
|
||||||
|
u8 rx_queues;
|
||||||
|
u8 rx_bds_per_q;
|
||||||
|
u8 bp_in_en_shift;
|
||||||
|
u32 bp_in_mask;
|
||||||
|
u8 hfb_filter_cnt;
|
||||||
|
u8 hfb_filter_size;
|
||||||
|
u8 qtag_mask;
|
||||||
|
u16 tbuf_offset;
|
||||||
|
u32 hfb_offset;
|
||||||
|
u32 hfb_reg_offset;
|
||||||
|
u32 rdma_offset;
|
||||||
|
u32 tdma_offset;
|
||||||
|
u32 words_per_bd;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_skb_cb {
|
||||||
|
struct enet_cb *first_cb; /* First control block of SKB */
|
||||||
|
struct enet_cb *last_cb; /* Last control block of SKB */
|
||||||
|
unsigned int bytes_sent; /* bytes on the wire (no TSB) */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GENET_CB(skb) ((struct bcmgenet_skb_cb *)((skb)->cb))
|
||||||
|
|
||||||
|
struct bcmgenet_tx_ring {
|
||||||
|
spinlock_t lock; /* ring lock */
|
||||||
|
struct napi_struct napi; /* NAPI per tx queue */
|
||||||
|
unsigned long packets;
|
||||||
|
unsigned long bytes;
|
||||||
|
unsigned int index; /* ring index */
|
||||||
|
unsigned int queue; /* queue index */
|
||||||
|
struct enet_cb *cbs; /* tx ring buffer control block*/
|
||||||
|
unsigned int size; /* size of each tx ring */
|
||||||
|
unsigned int clean_ptr; /* Tx ring clean pointer */
|
||||||
|
unsigned int c_index; /* last consumer index of each ring*/
|
||||||
|
unsigned int free_bds; /* # of free bds for each ring */
|
||||||
|
unsigned int write_ptr; /* Tx ring write pointer SW copy */
|
||||||
|
unsigned int prod_index; /* Tx ring producer index SW copy */
|
||||||
|
unsigned int cb_ptr; /* Tx ring initial CB ptr */
|
||||||
|
unsigned int end_ptr; /* Tx ring end CB ptr */
|
||||||
|
void (*int_enable)(struct bcmgenet_tx_ring *);
|
||||||
|
void (*int_disable)(struct bcmgenet_tx_ring *);
|
||||||
|
struct bcmgenet_priv *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_net_dim {
|
||||||
|
u16 use_dim;
|
||||||
|
u16 event_ctr;
|
||||||
|
unsigned long packets;
|
||||||
|
unsigned long bytes;
|
||||||
|
struct dim dim;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_rx_ring {
|
||||||
|
struct napi_struct napi; /* Rx NAPI struct */
|
||||||
|
unsigned long bytes;
|
||||||
|
unsigned long packets;
|
||||||
|
unsigned long errors;
|
||||||
|
unsigned long dropped;
|
||||||
|
unsigned int index; /* Rx ring index */
|
||||||
|
struct enet_cb *cbs; /* Rx ring buffer control block */
|
||||||
|
unsigned int size; /* Rx ring size */
|
||||||
|
unsigned int c_index; /* Rx last consumer index */
|
||||||
|
unsigned int read_ptr; /* Rx ring read pointer */
|
||||||
|
unsigned int cb_ptr; /* Rx ring initial CB ptr */
|
||||||
|
unsigned int end_ptr; /* Rx ring end CB ptr */
|
||||||
|
unsigned int old_discards;
|
||||||
|
struct bcmgenet_net_dim dim;
|
||||||
|
u32 rx_max_coalesced_frames;
|
||||||
|
u32 rx_coalesce_usecs;
|
||||||
|
void (*int_enable)(struct bcmgenet_rx_ring *);
|
||||||
|
void (*int_disable)(struct bcmgenet_rx_ring *);
|
||||||
|
struct bcmgenet_priv *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum bcmgenet_rxnfc_state {
|
||||||
|
BCMGENET_RXNFC_STATE_UNUSED = 0,
|
||||||
|
BCMGENET_RXNFC_STATE_DISABLED,
|
||||||
|
BCMGENET_RXNFC_STATE_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bcmgenet_rxnfc_rule {
|
||||||
|
struct list_head list;
|
||||||
|
struct ethtool_rx_flow_spec fs;
|
||||||
|
enum bcmgenet_rxnfc_state state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* device context */
|
||||||
|
struct bcmgenet_priv {
|
||||||
|
void __iomem *base;
|
||||||
|
enum bcmgenet_version version;
|
||||||
|
struct net_device *dev;
|
||||||
|
|
||||||
|
/* transmit variables */
|
||||||
|
void __iomem *tx_bds;
|
||||||
|
struct enet_cb *tx_cbs;
|
||||||
|
unsigned int num_tx_bds;
|
||||||
|
|
||||||
|
struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
|
||||||
|
|
||||||
|
/* receive variables */
|
||||||
|
void __iomem *rx_bds;
|
||||||
|
struct enet_cb *rx_cbs;
|
||||||
|
unsigned int num_rx_bds;
|
||||||
|
unsigned int rx_buf_len;
|
||||||
|
struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
|
||||||
|
struct list_head rxnfc_list;
|
||||||
|
|
||||||
|
struct bcmgenet_rx_ring rx_rings[DESC_INDEX + 1];
|
||||||
|
|
||||||
|
/* other misc variables */
|
||||||
|
struct bcmgenet_hw_params *hw_params;
|
||||||
|
unsigned autoneg_pause:1;
|
||||||
|
unsigned tx_pause:1;
|
||||||
|
unsigned rx_pause:1;
|
||||||
|
|
||||||
|
/* MDIO bus variables */
|
||||||
|
wait_queue_head_t wq;
|
||||||
|
bool internal_phy;
|
||||||
|
struct device_node *phy_dn;
|
||||||
|
struct device_node *mdio_dn;
|
||||||
|
struct mii_bus *mii_bus;
|
||||||
|
u16 gphy_rev;
|
||||||
|
struct clk *clk_eee;
|
||||||
|
bool clk_eee_enabled;
|
||||||
|
|
||||||
|
/* PHY device variables */
|
||||||
|
phy_interface_t phy_interface;
|
||||||
|
int phy_addr;
|
||||||
|
int ext_phy;
|
||||||
|
bool ephy_16nm;
|
||||||
|
|
||||||
|
/* Interrupt variables */
|
||||||
|
struct work_struct bcmgenet_irq_work;
|
||||||
|
int irq0;
|
||||||
|
int irq1;
|
||||||
|
int wol_irq;
|
||||||
|
bool wol_irq_disabled;
|
||||||
|
|
||||||
|
/* shared status */
|
||||||
|
spinlock_t lock;
|
||||||
|
unsigned int irq0_stat;
|
||||||
|
|
||||||
|
/* HW descriptors/checksum variables */
|
||||||
|
bool crc_fwd_en;
|
||||||
|
|
||||||
|
u32 dma_max_burst_length;
|
||||||
|
|
||||||
|
u32 msg_enable;
|
||||||
|
|
||||||
|
struct clk *clk;
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct platform_device *mii_pdev;
|
||||||
|
|
||||||
|
/* WOL */
|
||||||
|
struct clk *clk_wol;
|
||||||
|
u32 wolopts;
|
||||||
|
u8 sopass[SOPASS_MAX];
|
||||||
|
bool wol_active;
|
||||||
|
|
||||||
|
struct bcmgenet_mib_counters mib;
|
||||||
|
|
||||||
|
struct ethtool_eee eee;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GENET_IO_MACRO(name, offset) \
|
||||||
|
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
|
||||||
|
u32 off) \
|
||||||
|
{ \
|
||||||
|
/* MIPS chips strapped for BE will automagically configure the \
|
||||||
|
* peripheral registers for CPU-native byte order. \
|
||||||
|
*/ \
|
||||||
|
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||||
|
return __raw_readl(priv->base + offset + off); \
|
||||||
|
else \
|
||||||
|
return readl_relaxed(priv->base + offset + off); \
|
||||||
|
} \
|
||||||
|
static inline void bcmgenet_##name##_writel(struct bcmgenet_priv *priv, \
|
||||||
|
u32 val, u32 off) \
|
||||||
|
{ \
|
||||||
|
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||||
|
__raw_writel(val, priv->base + offset + off); \
|
||||||
|
else \
|
||||||
|
writel_relaxed(val, priv->base + offset + off); \
|
||||||
|
}
|
||||||
|
|
||||||
|
GENET_IO_MACRO(ext, GENET_EXT_OFF);
|
||||||
|
GENET_IO_MACRO(umac, GENET_UMAC_OFF);
|
||||||
|
GENET_IO_MACRO(sys, GENET_SYS_OFF);
|
||||||
|
|
||||||
|
/* interrupt l2 registers accessors */
|
||||||
|
GENET_IO_MACRO(intrl2_0, GENET_INTRL2_0_OFF);
|
||||||
|
GENET_IO_MACRO(intrl2_1, GENET_INTRL2_1_OFF);
|
||||||
|
|
||||||
|
/* HFB register accessors */
|
||||||
|
GENET_IO_MACRO(hfb, priv->hw_params->hfb_offset);
|
||||||
|
|
||||||
|
/* GENET v2+ HFB control and filter len helpers */
|
||||||
|
GENET_IO_MACRO(hfb_reg, priv->hw_params->hfb_reg_offset);
|
||||||
|
|
||||||
|
/* RBUF register accessors */
|
||||||
|
GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
|
||||||
|
|
||||||
|
/* MDIO routines */
|
||||||
|
int bcmgenet_mii_init(struct net_device *dev);
|
||||||
|
int bcmgenet_mii_config(struct net_device *dev, bool init);
|
||||||
|
int bcmgenet_mii_probe(struct net_device *dev);
|
||||||
|
void bcmgenet_mii_exit(struct net_device *dev);
|
||||||
|
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx);
|
||||||
|
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
|
||||||
|
void bcmgenet_mii_setup(struct net_device *dev);
|
||||||
|
|
||||||
|
/* Wake-on-LAN routines */
|
||||||
|
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||||
|
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||||
|
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode);
|
||||||
|
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode);
|
||||||
|
|
||||||
|
void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
|
||||||
|
bool tx_lpi_enabled);
|
||||||
|
|
||||||
|
#endif /* __BCMGENET_H__ */
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2020 Broadcom
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "bcmgenet_wol: " fmt
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <net/arp.h>
|
||||||
|
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/inetdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
|
||||||
|
#include "bcmgenet-6.1-ethercat.h"
|
||||||
|
|
||||||
|
/* ethtool function - get WOL (Wake on LAN) settings, Only Magic Packet
|
||||||
|
* Detection is supported through ethtool
|
||||||
|
*/
|
||||||
|
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
|
||||||
|
if (!device_can_wakeup(kdev)) {
|
||||||
|
wol->supported = 0;
|
||||||
|
wol->wolopts = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
|
||||||
|
wol->wolopts = priv->wolopts;
|
||||||
|
memset(wol->sopass, 0, sizeof(wol->sopass));
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||||
|
memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ethtool function - set WOL (Wake on LAN) settings.
|
||||||
|
* Only for magic packet detection mode.
|
||||||
|
*/
|
||||||
|
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
|
||||||
|
if (!device_can_wakeup(kdev))
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||||
|
memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
|
||||||
|
|
||||||
|
/* Flag the device and relevant IRQ as wakeup capable */
|
||||||
|
if (wol->wolopts) {
|
||||||
|
device_set_wakeup_enable(kdev, 1);
|
||||||
|
/* Avoid unbalanced enable_irq_wake calls */
|
||||||
|
if (priv->wol_irq_disabled)
|
||||||
|
enable_irq_wake(priv->wol_irq);
|
||||||
|
priv->wol_irq_disabled = false;
|
||||||
|
} else {
|
||||||
|
device_set_wakeup_enable(kdev, 0);
|
||||||
|
/* Avoid unbalanced disable_irq_wake calls */
|
||||||
|
if (!priv->wol_irq_disabled)
|
||||||
|
disable_irq_wake(priv->wol_irq);
|
||||||
|
priv->wol_irq_disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->wolopts = wol->wolopts;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct net_device *dev = priv->dev;
|
||||||
|
int retries = 0;
|
||||||
|
|
||||||
|
while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
|
||||||
|
& RBUF_STATUS_WOL)) {
|
||||||
|
retries++;
|
||||||
|
if (retries > 5) {
|
||||||
|
netdev_crit(dev, "polling wol mode timeout\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bcmgenet_set_mpd_password(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
bcmgenet_umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
|
||||||
|
UMAC_MPD_PW_MS);
|
||||||
|
bcmgenet_umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
|
||||||
|
UMAC_MPD_PW_LS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode)
|
||||||
|
{
|
||||||
|
struct net_device *dev = priv->dev;
|
||||||
|
struct bcmgenet_rxnfc_rule *rule;
|
||||||
|
u32 reg, hfb_ctrl_reg, hfb_enable = 0;
|
||||||
|
int retries = 0;
|
||||||
|
|
||||||
|
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||||
|
netif_err(priv, wol, dev, "unsupported mode: %d\n", mode);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't suspend with WoL if MAC is still in reset */
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
if (reg & CMD_SW_RESET)
|
||||||
|
reg &= ~CMD_SW_RESET;
|
||||||
|
|
||||||
|
/* disable RX */
|
||||||
|
reg &= ~CMD_RX_EN;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
mdelay(10);
|
||||||
|
|
||||||
|
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||||
|
reg |= MPD_EN;
|
||||||
|
if (priv->wolopts & WAKE_MAGICSECURE) {
|
||||||
|
bcmgenet_set_mpd_password(priv);
|
||||||
|
reg |= MPD_PW_EN;
|
||||||
|
}
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
hfb_ctrl_reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||||
|
if (priv->wolopts & WAKE_FILTER) {
|
||||||
|
list_for_each_entry(rule, &priv->rxnfc_list, list)
|
||||||
|
if (rule->fs.ring_cookie == RX_CLS_FLOW_WAKE)
|
||||||
|
hfb_enable |= (1 << rule->fs.location);
|
||||||
|
reg = (hfb_ctrl_reg & ~RBUF_HFB_EN) | RBUF_ACPI_EN;
|
||||||
|
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not leave UniMAC in MPD mode only */
|
||||||
|
retries = bcmgenet_poll_wol_status(priv);
|
||||||
|
if (retries < 0) {
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||||
|
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||||
|
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||||
|
return retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
|
||||||
|
retries);
|
||||||
|
|
||||||
|
clk_prepare_enable(priv->clk_wol);
|
||||||
|
priv->wol_active = 1;
|
||||||
|
|
||||||
|
if (hfb_enable) {
|
||||||
|
bcmgenet_hfb_reg_writel(priv, hfb_enable,
|
||||||
|
HFB_FLT_ENABLE_V3PLUS + 4);
|
||||||
|
hfb_ctrl_reg = RBUF_HFB_EN | RBUF_ACPI_EN;
|
||||||
|
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable CRC forward */
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
priv->crc_fwd_en = 1;
|
||||||
|
reg |= CMD_CRC_FWD;
|
||||||
|
|
||||||
|
/* Receiver must be enabled for WOL MP detection */
|
||||||
|
reg |= CMD_RX_EN;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
|
||||||
|
reg = UMAC_IRQ_MPD_R;
|
||||||
|
if (hfb_enable)
|
||||||
|
reg |= UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM;
|
||||||
|
|
||||||
|
bcmgenet_intrl2_0_writel(priv, reg, INTRL2_CPU_MASK_CLEAR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||||
|
netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->wol_active)
|
||||||
|
return; /* failed to suspend so skip the rest */
|
||||||
|
|
||||||
|
priv->wol_active = 0;
|
||||||
|
clk_disable_unprepare(priv->clk_wol);
|
||||||
|
priv->crc_fwd_en = 0;
|
||||||
|
|
||||||
|
/* Disable Magic Packet Detection */
|
||||||
|
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||||
|
if (!(reg & MPD_EN))
|
||||||
|
return; /* already reset so skip the rest */
|
||||||
|
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable WAKE_FILTER Detection */
|
||||||
|
if (priv->wolopts & WAKE_FILTER) {
|
||||||
|
reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||||
|
if (!(reg & RBUF_ACPI_EN))
|
||||||
|
return; /* already reset so skip the rest */
|
||||||
|
reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
|
||||||
|
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable CRC Forward */
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
reg &= ~CMD_CRC_FWD;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2020 Broadcom
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "bcmgenet_wol: " fmt
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <net/arp.h>
|
||||||
|
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/inetdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
|
||||||
|
#include "bcmgenet.h"
|
||||||
|
|
||||||
|
/* ethtool function - get WOL (Wake on LAN) settings, Only Magic Packet
|
||||||
|
* Detection is supported through ethtool
|
||||||
|
*/
|
||||||
|
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
|
||||||
|
if (!device_can_wakeup(kdev)) {
|
||||||
|
wol->supported = 0;
|
||||||
|
wol->wolopts = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
|
||||||
|
wol->wolopts = priv->wolopts;
|
||||||
|
memset(wol->sopass, 0, sizeof(wol->sopass));
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||||
|
memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ethtool function - set WOL (Wake on LAN) settings.
|
||||||
|
* Only for magic packet detection mode.
|
||||||
|
*/
|
||||||
|
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
|
||||||
|
if (!device_can_wakeup(kdev))
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||||
|
memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
|
||||||
|
|
||||||
|
/* Flag the device and relevant IRQ as wakeup capable */
|
||||||
|
if (wol->wolopts) {
|
||||||
|
device_set_wakeup_enable(kdev, 1);
|
||||||
|
/* Avoid unbalanced enable_irq_wake calls */
|
||||||
|
if (priv->wol_irq_disabled)
|
||||||
|
enable_irq_wake(priv->wol_irq);
|
||||||
|
priv->wol_irq_disabled = false;
|
||||||
|
} else {
|
||||||
|
device_set_wakeup_enable(kdev, 0);
|
||||||
|
/* Avoid unbalanced disable_irq_wake calls */
|
||||||
|
if (!priv->wol_irq_disabled)
|
||||||
|
disable_irq_wake(priv->wol_irq);
|
||||||
|
priv->wol_irq_disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->wolopts = wol->wolopts;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct net_device *dev = priv->dev;
|
||||||
|
int retries = 0;
|
||||||
|
|
||||||
|
while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
|
||||||
|
& RBUF_STATUS_WOL)) {
|
||||||
|
retries++;
|
||||||
|
if (retries > 5) {
|
||||||
|
netdev_crit(dev, "polling wol mode timeout\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bcmgenet_set_mpd_password(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
bcmgenet_umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
|
||||||
|
UMAC_MPD_PW_MS);
|
||||||
|
bcmgenet_umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
|
||||||
|
UMAC_MPD_PW_LS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode)
|
||||||
|
{
|
||||||
|
struct net_device *dev = priv->dev;
|
||||||
|
struct bcmgenet_rxnfc_rule *rule;
|
||||||
|
u32 reg, hfb_ctrl_reg, hfb_enable = 0;
|
||||||
|
int retries = 0;
|
||||||
|
|
||||||
|
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||||
|
netif_err(priv, wol, dev, "unsupported mode: %d\n", mode);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't suspend with WoL if MAC is still in reset */
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
if (reg & CMD_SW_RESET)
|
||||||
|
reg &= ~CMD_SW_RESET;
|
||||||
|
|
||||||
|
/* disable RX */
|
||||||
|
reg &= ~CMD_RX_EN;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
mdelay(10);
|
||||||
|
|
||||||
|
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||||
|
reg |= MPD_EN;
|
||||||
|
if (priv->wolopts & WAKE_MAGICSECURE) {
|
||||||
|
bcmgenet_set_mpd_password(priv);
|
||||||
|
reg |= MPD_PW_EN;
|
||||||
|
}
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
hfb_ctrl_reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||||
|
if (priv->wolopts & WAKE_FILTER) {
|
||||||
|
list_for_each_entry(rule, &priv->rxnfc_list, list)
|
||||||
|
if (rule->fs.ring_cookie == RX_CLS_FLOW_WAKE)
|
||||||
|
hfb_enable |= (1 << rule->fs.location);
|
||||||
|
reg = (hfb_ctrl_reg & ~RBUF_HFB_EN) | RBUF_ACPI_EN;
|
||||||
|
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not leave UniMAC in MPD mode only */
|
||||||
|
retries = bcmgenet_poll_wol_status(priv);
|
||||||
|
if (retries < 0) {
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||||
|
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||||
|
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||||
|
return retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
|
||||||
|
retries);
|
||||||
|
|
||||||
|
clk_prepare_enable(priv->clk_wol);
|
||||||
|
priv->wol_active = 1;
|
||||||
|
|
||||||
|
if (hfb_enable) {
|
||||||
|
bcmgenet_hfb_reg_writel(priv, hfb_enable,
|
||||||
|
HFB_FLT_ENABLE_V3PLUS + 4);
|
||||||
|
hfb_ctrl_reg = RBUF_HFB_EN | RBUF_ACPI_EN;
|
||||||
|
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable CRC forward */
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
priv->crc_fwd_en = 1;
|
||||||
|
reg |= CMD_CRC_FWD;
|
||||||
|
|
||||||
|
/* Receiver must be enabled for WOL MP detection */
|
||||||
|
reg |= CMD_RX_EN;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
|
||||||
|
reg = UMAC_IRQ_MPD_R;
|
||||||
|
if (hfb_enable)
|
||||||
|
reg |= UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM;
|
||||||
|
|
||||||
|
bcmgenet_intrl2_0_writel(priv, reg, INTRL2_CPU_MASK_CLEAR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||||
|
enum bcmgenet_power_mode mode)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||||
|
netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->wol_active)
|
||||||
|
return; /* failed to suspend so skip the rest */
|
||||||
|
|
||||||
|
priv->wol_active = 0;
|
||||||
|
clk_disable_unprepare(priv->clk_wol);
|
||||||
|
priv->crc_fwd_en = 0;
|
||||||
|
|
||||||
|
/* Disable Magic Packet Detection */
|
||||||
|
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||||
|
if (!(reg & MPD_EN))
|
||||||
|
return; /* already reset so skip the rest */
|
||||||
|
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable WAKE_FILTER Detection */
|
||||||
|
if (priv->wolopts & WAKE_FILTER) {
|
||||||
|
reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||||
|
if (!(reg & RBUF_ACPI_EN))
|
||||||
|
return; /* already reset so skip the rest */
|
||||||
|
reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
|
||||||
|
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable CRC Forward */
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
reg &= ~CMD_CRC_FWD;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,671 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Broadcom GENET MDIO routines
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2017 Broadcom
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/phy_fixed.h>
|
||||||
|
#include <linux/brcmphy.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_net.h>
|
||||||
|
#include <linux/of_mdio.h>
|
||||||
|
#include <linux/platform_data/bcmgenet.h>
|
||||||
|
#include <linux/platform_data/mdio-bcm-unimac.h>
|
||||||
|
|
||||||
|
#include "bcmgenet-6.1-ethercat.h"
|
||||||
|
|
||||||
|
static void bcmgenet_mac_config(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
u32 reg, cmd_bits = 0;
|
||||||
|
|
||||||
|
/* speed */
|
||||||
|
if (phydev->speed == SPEED_1000)
|
||||||
|
cmd_bits = CMD_SPEED_1000;
|
||||||
|
else if (phydev->speed == SPEED_100)
|
||||||
|
cmd_bits = CMD_SPEED_100;
|
||||||
|
else
|
||||||
|
cmd_bits = CMD_SPEED_10;
|
||||||
|
cmd_bits <<= CMD_SPEED_SHIFT;
|
||||||
|
|
||||||
|
/* duplex */
|
||||||
|
if (phydev->duplex != DUPLEX_FULL) {
|
||||||
|
cmd_bits |= CMD_HD_EN |
|
||||||
|
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
|
||||||
|
} else {
|
||||||
|
/* pause capability defaults to Symmetric */
|
||||||
|
if (priv->autoneg_pause) {
|
||||||
|
bool tx_pause = 0, rx_pause = 0;
|
||||||
|
|
||||||
|
if (phydev->autoneg)
|
||||||
|
phy_get_pause(phydev, &tx_pause, &rx_pause);
|
||||||
|
|
||||||
|
if (!tx_pause)
|
||||||
|
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||||
|
if (!rx_pause)
|
||||||
|
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Manual override */
|
||||||
|
if (!priv->rx_pause)
|
||||||
|
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||||
|
if (!priv->tx_pause)
|
||||||
|
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program UMAC and RGMII block based on established
|
||||||
|
* link speed, duplex, and pause. The speed set in
|
||||||
|
* umac->cmd tell RGMII block which clock to use for
|
||||||
|
* transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
|
||||||
|
* Receive clock is provided by the PHY.
|
||||||
|
*/
|
||||||
|
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||||
|
reg &= ~OOB_DISABLE;
|
||||||
|
reg |= RGMII_LINK;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||||
|
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
|
||||||
|
CMD_HD_EN |
|
||||||
|
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
|
||||||
|
reg |= cmd_bits;
|
||||||
|
if (reg & CMD_SW_RESET) {
|
||||||
|
reg &= ~CMD_SW_RESET;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
udelay(2);
|
||||||
|
reg |= CMD_TX_EN | CMD_RX_EN;
|
||||||
|
}
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
|
||||||
|
priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
|
||||||
|
bcmgenet_eee_enable_set(dev,
|
||||||
|
priv->eee.eee_enabled && priv->eee.eee_active,
|
||||||
|
priv->eee.tx_lpi_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup netdev link state when PHY link status change and
|
||||||
|
* update UMAC and RGMII block when link up
|
||||||
|
*/
|
||||||
|
void bcmgenet_mii_setup(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (phydev->link)
|
||||||
|
bcmgenet_mac_config(dev);
|
||||||
|
if (priv->ecdev)
|
||||||
|
ecdev_set_link(priv->ecdev, phydev->link);
|
||||||
|
phy_print_status(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
|
||||||
|
struct fixed_phy_status *status)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (dev && dev->phydev && status) {
|
||||||
|
priv = netdev_priv(dev);
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MODE);
|
||||||
|
status->link = !!(reg & MODE_LINK_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx)
|
||||||
|
{
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising, rx);
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising,
|
||||||
|
rx | tx);
|
||||||
|
phy_start_aneg(phydev);
|
||||||
|
|
||||||
|
mutex_lock(&phydev->lock);
|
||||||
|
if (phydev->link)
|
||||||
|
bcmgenet_mac_config(dev);
|
||||||
|
mutex_unlock(&phydev->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
u32 reg = 0;
|
||||||
|
|
||||||
|
/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
|
||||||
|
if (GENET_IS_V4(priv) || priv->ephy_16nm) {
|
||||||
|
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
|
||||||
|
if (enable) {
|
||||||
|
reg &= ~EXT_CK25_DIS;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||||
|
EXT_CFG_IDDQ_GLOBAL_PWR);
|
||||||
|
reg |= EXT_GPHY_RESET;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
reg &= ~EXT_GPHY_RESET;
|
||||||
|
} else {
|
||||||
|
reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||||
|
EXT_GPHY_RESET | EXT_CFG_IDDQ_GLOBAL_PWR;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
mdelay(1);
|
||||||
|
reg |= EXT_CK25_DIS;
|
||||||
|
}
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
udelay(60);
|
||||||
|
} else {
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
|
||||||
|
fixed_phy_set_link_update(priv->dev->phydev,
|
||||||
|
bcmgenet_fixed_phy_link_update);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_mii_config(struct net_device *dev, bool init)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
const char *phy_name = NULL;
|
||||||
|
u32 id_mode_dis = 0;
|
||||||
|
u32 port_ctrl;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
switch (priv->phy_interface) {
|
||||||
|
case PHY_INTERFACE_MODE_INTERNAL:
|
||||||
|
phy_name = "internal PHY";
|
||||||
|
fallthrough;
|
||||||
|
case PHY_INTERFACE_MODE_MOCA:
|
||||||
|
/* Irrespective of the actually configured PHY speed (100 or
|
||||||
|
* 1000) GENETv4 only has an internal GPHY so we will just end
|
||||||
|
* up masking the Gigabit features from what we support, not
|
||||||
|
* switching to the EPHY
|
||||||
|
*/
|
||||||
|
if (GENET_IS_V4(priv))
|
||||||
|
port_ctrl = PORT_MODE_INT_GPHY;
|
||||||
|
else
|
||||||
|
port_ctrl = PORT_MODE_INT_EPHY;
|
||||||
|
|
||||||
|
if (!phy_name) {
|
||||||
|
phy_name = "MoCA";
|
||||||
|
if (!GENET_IS_V5(priv))
|
||||||
|
port_ctrl |= LED_ACT_SOURCE_MAC;
|
||||||
|
bcmgenet_moca_phy_setup(priv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_MII:
|
||||||
|
phy_name = "external MII";
|
||||||
|
phy_set_max_speed(phydev, SPEED_100);
|
||||||
|
port_ctrl = PORT_MODE_EXT_EPHY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_REVMII:
|
||||||
|
phy_name = "external RvMII";
|
||||||
|
/* of_mdiobus_register took care of reading the 'max-speed'
|
||||||
|
* PHY property for us, effectively limiting the PHY supported
|
||||||
|
* capabilities, use that knowledge to also configure the
|
||||||
|
* Reverse MII interface correctly.
|
||||||
|
*/
|
||||||
|
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||||
|
dev->phydev->supported))
|
||||||
|
port_ctrl = PORT_MODE_EXT_RVMII_50;
|
||||||
|
else
|
||||||
|
port_ctrl = PORT_MODE_EXT_RVMII_25;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_RGMII:
|
||||||
|
/* RGMII_NO_ID: TXC transitions at the same time as TXD
|
||||||
|
* (requires PCB or receiver-side delay)
|
||||||
|
*
|
||||||
|
* ID is implicitly disabled for 100Mbps (RG)MII operation.
|
||||||
|
*/
|
||||||
|
phy_name = "external RGMII (no delay)";
|
||||||
|
id_mode_dis = BIT(16);
|
||||||
|
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||||
|
/* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */
|
||||||
|
phy_name = "external RGMII (TX delay)";
|
||||||
|
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||||
|
phy_name = "external RGMII (RX delay)";
|
||||||
|
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||||
|
|
||||||
|
priv->ext_phy = !priv->internal_phy &&
|
||||||
|
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
|
||||||
|
|
||||||
|
/* This is an external PHY (xMII), so we need to enable the RGMII
|
||||||
|
* block for the interface to work
|
||||||
|
*/
|
||||||
|
if (priv->ext_phy) {
|
||||||
|
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||||
|
reg &= ~ID_MODE_DIS;
|
||||||
|
reg |= id_mode_dis;
|
||||||
|
if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
|
||||||
|
reg |= RGMII_MODE_EN_V123;
|
||||||
|
else
|
||||||
|
reg |= RGMII_MODE_EN;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init)
|
||||||
|
dev_info(kdev, "configuring instance for %s\n", phy_name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_mii_probe(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct device_node *dn = kdev->of_node;
|
||||||
|
phy_interface_t phy_iface = priv->phy_interface;
|
||||||
|
struct phy_device *phydev;
|
||||||
|
u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE |
|
||||||
|
PHY_BRCM_DIS_TXCRXC_NOENRGY |
|
||||||
|
PHY_BRCM_IDDQ_SUSPEND;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Communicate the integrated PHY revision */
|
||||||
|
if (priv->internal_phy)
|
||||||
|
phy_flags = priv->gphy_rev;
|
||||||
|
|
||||||
|
/* This is an ugly quirk but we have not been correctly interpreting
|
||||||
|
* the phy_interface values and we have done that across different
|
||||||
|
* drivers, so at least we are consistent in our mistakes.
|
||||||
|
*
|
||||||
|
* When the Generic PHY driver is in use either the PHY has been
|
||||||
|
* strapped or programmed correctly by the boot loader so we should
|
||||||
|
* stick to our incorrect interpretation since we have validated it.
|
||||||
|
*
|
||||||
|
* Now when a dedicated PHY driver is in use, we need to reverse the
|
||||||
|
* meaning of the phy_interface_mode values to something that the PHY
|
||||||
|
* driver will interpret and act on such that we have two mistakes
|
||||||
|
* canceling themselves so to speak. We only do this for the two
|
||||||
|
* modes that GENET driver officially supports on Broadcom STB chips:
|
||||||
|
* PHY_INTERFACE_MODE_RGMII and PHY_INTERFACE_MODE_RGMII_TXID. Other
|
||||||
|
* modes are not *officially* supported with the boot loader and the
|
||||||
|
* scripted environment generating Device Tree blobs for those
|
||||||
|
* platforms.
|
||||||
|
*
|
||||||
|
* Note that internal PHY, MoCA and fixed-link configurations are not
|
||||||
|
* affected because they use different phy_interface_t values or the
|
||||||
|
* Generic PHY driver.
|
||||||
|
*/
|
||||||
|
switch (priv->phy_interface) {
|
||||||
|
case PHY_INTERFACE_MODE_RGMII:
|
||||||
|
phy_iface = PHY_INTERFACE_MODE_RGMII_ID;
|
||||||
|
break;
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||||
|
phy_iface = PHY_INTERFACE_MODE_RGMII_RXID;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dn) {
|
||||||
|
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||||
|
phy_flags, phy_iface);
|
||||||
|
if (!phydev) {
|
||||||
|
pr_err("could not attach to PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (has_acpi_companion(kdev)) {
|
||||||
|
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||||
|
struct mii_bus *unimacbus;
|
||||||
|
|
||||||
|
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||||
|
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||||
|
|
||||||
|
unimacbus = mdio_find_bus(mdio_bus_id);
|
||||||
|
if (!unimacbus) {
|
||||||
|
pr_err("Unable to find mii\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
phydev = phy_find_first(unimacbus);
|
||||||
|
put_device(&unimacbus->dev);
|
||||||
|
if (!phydev) {
|
||||||
|
pr_err("Unable to find PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phydev = dev->phydev;
|
||||||
|
}
|
||||||
|
phydev->dev_flags = phy_flags;
|
||||||
|
|
||||||
|
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
|
||||||
|
phy_iface);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("could not attach to PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure port multiplexer based on what the probed PHY device since
|
||||||
|
* reading the 'max-speed' property determines the maximum supported
|
||||||
|
* PHY speed which is needed for bcmgenet_mii_config() to configure
|
||||||
|
* things appropriately.
|
||||||
|
*/
|
||||||
|
ret = bcmgenet_mii_config(dev, true);
|
||||||
|
if (ret) {
|
||||||
|
phy_disconnect(dev->phydev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The internal PHY has its link interrupts routed to the
|
||||||
|
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
|
||||||
|
* that prevents the signaling of link UP interrupts when
|
||||||
|
* the link operates at 10Mbps, so fallback to polling for
|
||||||
|
* those versions of GENET.
|
||||||
|
*/
|
||||||
|
if (priv->internal_phy && !GENET_IS_V5(priv))
|
||||||
|
dev->phydev->irq = PHY_MAC_INTERRUPT;
|
||||||
|
|
||||||
|
/* Indicate that the MAC is responsible for PHY PM */
|
||||||
|
dev->phydev->mac_managed_pm = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device_node *dn = priv->pdev->dev.of_node;
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
char *compat;
|
||||||
|
|
||||||
|
compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
|
||||||
|
if (!compat)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
priv->mdio_dn = of_get_compatible_child(dn, compat);
|
||||||
|
kfree(compat);
|
||||||
|
if (!priv->mdio_dn) {
|
||||||
|
dev_err(kdev, "unable to find MDIO bus node\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv->mdio_dn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bcmgenet_mii_pdata_init(struct bcmgenet_priv *priv,
|
||||||
|
struct unimac_mdio_pdata *ppd)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||||
|
|
||||||
|
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||||
|
/*
|
||||||
|
* Internal or external PHY with MDIO access
|
||||||
|
*/
|
||||||
|
if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR)
|
||||||
|
ppd->phy_mask = 1 << pd->phy_address;
|
||||||
|
else
|
||||||
|
ppd->phy_mask = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_wait(void *wait_func_data)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = wait_func_data;
|
||||||
|
|
||||||
|
wait_event_timeout(priv->wq,
|
||||||
|
!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
|
||||||
|
& MDIO_START_BUSY),
|
||||||
|
HZ / 100);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_register(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = priv->pdev;
|
||||||
|
struct bcmgenet_platform_data *pdata = pdev->dev.platform_data;
|
||||||
|
struct device_node *dn = pdev->dev.of_node;
|
||||||
|
struct unimac_mdio_pdata ppd;
|
||||||
|
struct platform_device *ppdev;
|
||||||
|
struct resource *pres, res;
|
||||||
|
int id, ret;
|
||||||
|
|
||||||
|
pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!pres) {
|
||||||
|
dev_err(&pdev->dev, "Invalid resource\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memset(&res, 0, sizeof(res));
|
||||||
|
memset(&ppd, 0, sizeof(ppd));
|
||||||
|
|
||||||
|
ppd.wait_func = bcmgenet_mii_wait;
|
||||||
|
ppd.wait_func_data = priv;
|
||||||
|
ppd.bus_name = "bcmgenet MII bus";
|
||||||
|
|
||||||
|
/* Unimac MDIO bus controller starts at UniMAC offset + MDIO_CMD
|
||||||
|
* and is 2 * 32-bits word long, 8 bytes total.
|
||||||
|
*/
|
||||||
|
res.start = pres->start + GENET_UMAC_OFF + UMAC_MDIO_CMD;
|
||||||
|
res.end = res.start + 8;
|
||||||
|
res.flags = IORESOURCE_MEM;
|
||||||
|
|
||||||
|
if (dn)
|
||||||
|
id = of_alias_get_id(dn, "eth");
|
||||||
|
else
|
||||||
|
id = pdev->id;
|
||||||
|
|
||||||
|
ppdev = platform_device_alloc(UNIMAC_MDIO_DRV_NAME, id);
|
||||||
|
if (!ppdev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Retain this platform_device pointer for later cleanup */
|
||||||
|
priv->mii_pdev = ppdev;
|
||||||
|
ppdev->dev.parent = &pdev->dev;
|
||||||
|
if (dn)
|
||||||
|
ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv);
|
||||||
|
else if (pdata)
|
||||||
|
bcmgenet_mii_pdata_init(priv, &ppd);
|
||||||
|
else
|
||||||
|
ppd.phy_mask = ~0;
|
||||||
|
|
||||||
|
ret = platform_device_add_resources(ppdev, &res, 1);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = platform_device_add(ppdev);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
platform_device_put(ppdev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_phy_interface_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
int phy_mode = device_get_phy_mode(kdev);
|
||||||
|
|
||||||
|
if (phy_mode < 0) {
|
||||||
|
dev_err(kdev, "invalid PHY mode property\n");
|
||||||
|
return phy_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->phy_interface = phy_mode;
|
||||||
|
|
||||||
|
/* We need to specifically look up whether this PHY interface is
|
||||||
|
* internal or not *before* we even try to probe the PHY driver
|
||||||
|
* over MDIO as we may have shut down the internal PHY for power
|
||||||
|
* saving purposes.
|
||||||
|
*/
|
||||||
|
if (priv->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
|
||||||
|
priv->internal_phy = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device_node *dn = priv->pdev->dev.of_node;
|
||||||
|
struct phy_device *phydev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Fetch the PHY phandle */
|
||||||
|
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
|
||||||
|
|
||||||
|
/* In the case of a fixed PHY, the DT node associated
|
||||||
|
* to the PHY is the Ethernet MAC DT node.
|
||||||
|
*/
|
||||||
|
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
|
||||||
|
ret = of_phy_register_fixed_link(dn);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->phy_dn = of_node_get(dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the link mode */
|
||||||
|
ret = bcmgenet_phy_interface_init(priv);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Make sure we initialize MoCA PHYs with a link down */
|
||||||
|
if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
|
||||||
|
phydev = of_phy_find_device(dn);
|
||||||
|
if (phydev) {
|
||||||
|
phydev->link = 0;
|
||||||
|
put_device(&phydev->mdio.dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||||
|
char phy_name[MII_BUS_ID_SIZE + 3];
|
||||||
|
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||||
|
struct phy_device *phydev;
|
||||||
|
|
||||||
|
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||||
|
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||||
|
|
||||||
|
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||||
|
snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
|
||||||
|
mdio_bus_id, pd->phy_address);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal or external PHY with MDIO access
|
||||||
|
*/
|
||||||
|
phydev = phy_attach(priv->dev, phy_name, pd->phy_interface);
|
||||||
|
if (IS_ERR(phydev)) {
|
||||||
|
dev_err(kdev, "failed to register PHY device\n");
|
||||||
|
return PTR_ERR(phydev);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* MoCA port or no MDIO access.
|
||||||
|
* Use fixed PHY to represent the link layer.
|
||||||
|
*/
|
||||||
|
struct fixed_phy_status fphy_status = {
|
||||||
|
.link = 1,
|
||||||
|
.speed = pd->phy_speed,
|
||||||
|
.duplex = pd->phy_duplex,
|
||||||
|
.pause = 0,
|
||||||
|
.asym_pause = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
|
||||||
|
if (!phydev || IS_ERR(phydev)) {
|
||||||
|
dev_err(kdev, "failed to register fixed PHY device\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we initialize MoCA PHYs with a link down */
|
||||||
|
phydev->link = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->phy_interface = pd->phy_interface;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct device_node *dn = kdev->of_node;
|
||||||
|
|
||||||
|
if (dn)
|
||||||
|
return bcmgenet_mii_of_init(priv);
|
||||||
|
else if (has_acpi_companion(kdev))
|
||||||
|
return bcmgenet_phy_interface_init(priv);
|
||||||
|
else
|
||||||
|
return bcmgenet_mii_pd_init(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_mii_init(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = bcmgenet_mii_register(priv);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = bcmgenet_mii_bus_init(priv);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
bcmgenet_mii_exit(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_mii_exit(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device_node *dn = priv->pdev->dev.of_node;
|
||||||
|
|
||||||
|
if (of_phy_is_fixed_link(dn))
|
||||||
|
of_phy_deregister_fixed_link(dn);
|
||||||
|
of_node_put(priv->phy_dn);
|
||||||
|
platform_device_unregister(priv->mii_pdev);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,668 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Broadcom GENET MDIO routines
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2017 Broadcom
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/mii.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/phy_fixed.h>
|
||||||
|
#include <linux/brcmphy.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_net.h>
|
||||||
|
#include <linux/of_mdio.h>
|
||||||
|
#include <linux/platform_data/bcmgenet.h>
|
||||||
|
#include <linux/platform_data/mdio-bcm-unimac.h>
|
||||||
|
|
||||||
|
#include "bcmgenet.h"
|
||||||
|
|
||||||
|
static void bcmgenet_mac_config(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
u32 reg, cmd_bits = 0;
|
||||||
|
|
||||||
|
/* speed */
|
||||||
|
if (phydev->speed == SPEED_1000)
|
||||||
|
cmd_bits = CMD_SPEED_1000;
|
||||||
|
else if (phydev->speed == SPEED_100)
|
||||||
|
cmd_bits = CMD_SPEED_100;
|
||||||
|
else
|
||||||
|
cmd_bits = CMD_SPEED_10;
|
||||||
|
cmd_bits <<= CMD_SPEED_SHIFT;
|
||||||
|
|
||||||
|
/* duplex */
|
||||||
|
if (phydev->duplex != DUPLEX_FULL) {
|
||||||
|
cmd_bits |= CMD_HD_EN |
|
||||||
|
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
|
||||||
|
} else {
|
||||||
|
/* pause capability defaults to Symmetric */
|
||||||
|
if (priv->autoneg_pause) {
|
||||||
|
bool tx_pause = 0, rx_pause = 0;
|
||||||
|
|
||||||
|
if (phydev->autoneg)
|
||||||
|
phy_get_pause(phydev, &tx_pause, &rx_pause);
|
||||||
|
|
||||||
|
if (!tx_pause)
|
||||||
|
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||||
|
if (!rx_pause)
|
||||||
|
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Manual override */
|
||||||
|
if (!priv->rx_pause)
|
||||||
|
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||||
|
if (!priv->tx_pause)
|
||||||
|
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program UMAC and RGMII block based on established
|
||||||
|
* link speed, duplex, and pause. The speed set in
|
||||||
|
* umac->cmd tell RGMII block which clock to use for
|
||||||
|
* transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
|
||||||
|
* Receive clock is provided by the PHY.
|
||||||
|
*/
|
||||||
|
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||||
|
reg &= ~OOB_DISABLE;
|
||||||
|
reg |= RGMII_LINK;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||||
|
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||||
|
reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
|
||||||
|
CMD_HD_EN |
|
||||||
|
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
|
||||||
|
reg |= cmd_bits;
|
||||||
|
if (reg & CMD_SW_RESET) {
|
||||||
|
reg &= ~CMD_SW_RESET;
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
udelay(2);
|
||||||
|
reg |= CMD_TX_EN | CMD_RX_EN;
|
||||||
|
}
|
||||||
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||||
|
|
||||||
|
priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
|
||||||
|
bcmgenet_eee_enable_set(dev,
|
||||||
|
priv->eee.eee_enabled && priv->eee.eee_active,
|
||||||
|
priv->eee.tx_lpi_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup netdev link state when PHY link status change and
|
||||||
|
* update UMAC and RGMII block when link up
|
||||||
|
*/
|
||||||
|
void bcmgenet_mii_setup(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
|
||||||
|
if (phydev->link)
|
||||||
|
bcmgenet_mac_config(dev);
|
||||||
|
phy_print_status(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
|
||||||
|
struct fixed_phy_status *status)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (dev && dev->phydev && status) {
|
||||||
|
priv = netdev_priv(dev);
|
||||||
|
reg = bcmgenet_umac_readl(priv, UMAC_MODE);
|
||||||
|
status->link = !!(reg & MODE_LINK_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx)
|
||||||
|
{
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising, rx);
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising,
|
||||||
|
rx | tx);
|
||||||
|
phy_start_aneg(phydev);
|
||||||
|
|
||||||
|
mutex_lock(&phydev->lock);
|
||||||
|
if (phydev->link)
|
||||||
|
bcmgenet_mac_config(dev);
|
||||||
|
mutex_unlock(&phydev->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
u32 reg = 0;
|
||||||
|
|
||||||
|
/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
|
||||||
|
if (GENET_IS_V4(priv) || priv->ephy_16nm) {
|
||||||
|
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
|
||||||
|
if (enable) {
|
||||||
|
reg &= ~EXT_CK25_DIS;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||||
|
EXT_CFG_IDDQ_GLOBAL_PWR);
|
||||||
|
reg |= EXT_GPHY_RESET;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
reg &= ~EXT_GPHY_RESET;
|
||||||
|
} else {
|
||||||
|
reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||||
|
EXT_GPHY_RESET | EXT_CFG_IDDQ_GLOBAL_PWR;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
mdelay(1);
|
||||||
|
reg |= EXT_CK25_DIS;
|
||||||
|
}
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||||
|
udelay(60);
|
||||||
|
} else {
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
|
||||||
|
fixed_phy_set_link_update(priv->dev->phydev,
|
||||||
|
bcmgenet_fixed_phy_link_update);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_mii_config(struct net_device *dev, bool init)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct phy_device *phydev = dev->phydev;
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
const char *phy_name = NULL;
|
||||||
|
u32 id_mode_dis = 0;
|
||||||
|
u32 port_ctrl;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
switch (priv->phy_interface) {
|
||||||
|
case PHY_INTERFACE_MODE_INTERNAL:
|
||||||
|
phy_name = "internal PHY";
|
||||||
|
fallthrough;
|
||||||
|
case PHY_INTERFACE_MODE_MOCA:
|
||||||
|
/* Irrespective of the actually configured PHY speed (100 or
|
||||||
|
* 1000) GENETv4 only has an internal GPHY so we will just end
|
||||||
|
* up masking the Gigabit features from what we support, not
|
||||||
|
* switching to the EPHY
|
||||||
|
*/
|
||||||
|
if (GENET_IS_V4(priv))
|
||||||
|
port_ctrl = PORT_MODE_INT_GPHY;
|
||||||
|
else
|
||||||
|
port_ctrl = PORT_MODE_INT_EPHY;
|
||||||
|
|
||||||
|
if (!phy_name) {
|
||||||
|
phy_name = "MoCA";
|
||||||
|
if (!GENET_IS_V5(priv))
|
||||||
|
port_ctrl |= LED_ACT_SOURCE_MAC;
|
||||||
|
bcmgenet_moca_phy_setup(priv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_MII:
|
||||||
|
phy_name = "external MII";
|
||||||
|
phy_set_max_speed(phydev, SPEED_100);
|
||||||
|
port_ctrl = PORT_MODE_EXT_EPHY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_REVMII:
|
||||||
|
phy_name = "external RvMII";
|
||||||
|
/* of_mdiobus_register took care of reading the 'max-speed'
|
||||||
|
* PHY property for us, effectively limiting the PHY supported
|
||||||
|
* capabilities, use that knowledge to also configure the
|
||||||
|
* Reverse MII interface correctly.
|
||||||
|
*/
|
||||||
|
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||||
|
dev->phydev->supported))
|
||||||
|
port_ctrl = PORT_MODE_EXT_RVMII_50;
|
||||||
|
else
|
||||||
|
port_ctrl = PORT_MODE_EXT_RVMII_25;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_RGMII:
|
||||||
|
/* RGMII_NO_ID: TXC transitions at the same time as TXD
|
||||||
|
* (requires PCB or receiver-side delay)
|
||||||
|
*
|
||||||
|
* ID is implicitly disabled for 100Mbps (RG)MII operation.
|
||||||
|
*/
|
||||||
|
phy_name = "external RGMII (no delay)";
|
||||||
|
id_mode_dis = BIT(16);
|
||||||
|
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||||
|
/* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */
|
||||||
|
phy_name = "external RGMII (TX delay)";
|
||||||
|
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||||
|
phy_name = "external RGMII (RX delay)";
|
||||||
|
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||||
|
|
||||||
|
priv->ext_phy = !priv->internal_phy &&
|
||||||
|
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
|
||||||
|
|
||||||
|
/* This is an external PHY (xMII), so we need to enable the RGMII
|
||||||
|
* block for the interface to work
|
||||||
|
*/
|
||||||
|
if (priv->ext_phy) {
|
||||||
|
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||||
|
reg &= ~ID_MODE_DIS;
|
||||||
|
reg |= id_mode_dis;
|
||||||
|
if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
|
||||||
|
reg |= RGMII_MODE_EN_V123;
|
||||||
|
else
|
||||||
|
reg |= RGMII_MODE_EN;
|
||||||
|
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init)
|
||||||
|
dev_info(kdev, "configuring instance for %s\n", phy_name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_mii_probe(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct device_node *dn = kdev->of_node;
|
||||||
|
phy_interface_t phy_iface = priv->phy_interface;
|
||||||
|
struct phy_device *phydev;
|
||||||
|
u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE |
|
||||||
|
PHY_BRCM_DIS_TXCRXC_NOENRGY |
|
||||||
|
PHY_BRCM_IDDQ_SUSPEND;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Communicate the integrated PHY revision */
|
||||||
|
if (priv->internal_phy)
|
||||||
|
phy_flags = priv->gphy_rev;
|
||||||
|
|
||||||
|
/* This is an ugly quirk but we have not been correctly interpreting
|
||||||
|
* the phy_interface values and we have done that across different
|
||||||
|
* drivers, so at least we are consistent in our mistakes.
|
||||||
|
*
|
||||||
|
* When the Generic PHY driver is in use either the PHY has been
|
||||||
|
* strapped or programmed correctly by the boot loader so we should
|
||||||
|
* stick to our incorrect interpretation since we have validated it.
|
||||||
|
*
|
||||||
|
* Now when a dedicated PHY driver is in use, we need to reverse the
|
||||||
|
* meaning of the phy_interface_mode values to something that the PHY
|
||||||
|
* driver will interpret and act on such that we have two mistakes
|
||||||
|
* canceling themselves so to speak. We only do this for the two
|
||||||
|
* modes that GENET driver officially supports on Broadcom STB chips:
|
||||||
|
* PHY_INTERFACE_MODE_RGMII and PHY_INTERFACE_MODE_RGMII_TXID. Other
|
||||||
|
* modes are not *officially* supported with the boot loader and the
|
||||||
|
* scripted environment generating Device Tree blobs for those
|
||||||
|
* platforms.
|
||||||
|
*
|
||||||
|
* Note that internal PHY, MoCA and fixed-link configurations are not
|
||||||
|
* affected because they use different phy_interface_t values or the
|
||||||
|
* Generic PHY driver.
|
||||||
|
*/
|
||||||
|
switch (priv->phy_interface) {
|
||||||
|
case PHY_INTERFACE_MODE_RGMII:
|
||||||
|
phy_iface = PHY_INTERFACE_MODE_RGMII_ID;
|
||||||
|
break;
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||||
|
phy_iface = PHY_INTERFACE_MODE_RGMII_RXID;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dn) {
|
||||||
|
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||||
|
phy_flags, phy_iface);
|
||||||
|
if (!phydev) {
|
||||||
|
pr_err("could not attach to PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (has_acpi_companion(kdev)) {
|
||||||
|
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||||
|
struct mii_bus *unimacbus;
|
||||||
|
|
||||||
|
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||||
|
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||||
|
|
||||||
|
unimacbus = mdio_find_bus(mdio_bus_id);
|
||||||
|
if (!unimacbus) {
|
||||||
|
pr_err("Unable to find mii\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
phydev = phy_find_first(unimacbus);
|
||||||
|
put_device(&unimacbus->dev);
|
||||||
|
if (!phydev) {
|
||||||
|
pr_err("Unable to find PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phydev = dev->phydev;
|
||||||
|
}
|
||||||
|
phydev->dev_flags = phy_flags;
|
||||||
|
|
||||||
|
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
|
||||||
|
phy_iface);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("could not attach to PHY\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure port multiplexer based on what the probed PHY device since
|
||||||
|
* reading the 'max-speed' property determines the maximum supported
|
||||||
|
* PHY speed which is needed for bcmgenet_mii_config() to configure
|
||||||
|
* things appropriately.
|
||||||
|
*/
|
||||||
|
ret = bcmgenet_mii_config(dev, true);
|
||||||
|
if (ret) {
|
||||||
|
phy_disconnect(dev->phydev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The internal PHY has its link interrupts routed to the
|
||||||
|
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
|
||||||
|
* that prevents the signaling of link UP interrupts when
|
||||||
|
* the link operates at 10Mbps, so fallback to polling for
|
||||||
|
* those versions of GENET.
|
||||||
|
*/
|
||||||
|
if (priv->internal_phy && !GENET_IS_V5(priv))
|
||||||
|
dev->phydev->irq = PHY_MAC_INTERRUPT;
|
||||||
|
|
||||||
|
/* Indicate that the MAC is responsible for PHY PM */
|
||||||
|
dev->phydev->mac_managed_pm = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device_node *dn = priv->pdev->dev.of_node;
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
char *compat;
|
||||||
|
|
||||||
|
compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
|
||||||
|
if (!compat)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
priv->mdio_dn = of_get_compatible_child(dn, compat);
|
||||||
|
kfree(compat);
|
||||||
|
if (!priv->mdio_dn) {
|
||||||
|
dev_err(kdev, "unable to find MDIO bus node\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv->mdio_dn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bcmgenet_mii_pdata_init(struct bcmgenet_priv *priv,
|
||||||
|
struct unimac_mdio_pdata *ppd)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||||
|
|
||||||
|
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||||
|
/*
|
||||||
|
* Internal or external PHY with MDIO access
|
||||||
|
*/
|
||||||
|
if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR)
|
||||||
|
ppd->phy_mask = 1 << pd->phy_address;
|
||||||
|
else
|
||||||
|
ppd->phy_mask = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_wait(void *wait_func_data)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = wait_func_data;
|
||||||
|
|
||||||
|
wait_event_timeout(priv->wq,
|
||||||
|
!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
|
||||||
|
& MDIO_START_BUSY),
|
||||||
|
HZ / 100);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_register(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = priv->pdev;
|
||||||
|
struct bcmgenet_platform_data *pdata = pdev->dev.platform_data;
|
||||||
|
struct device_node *dn = pdev->dev.of_node;
|
||||||
|
struct unimac_mdio_pdata ppd;
|
||||||
|
struct platform_device *ppdev;
|
||||||
|
struct resource *pres, res;
|
||||||
|
int id, ret;
|
||||||
|
|
||||||
|
pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!pres) {
|
||||||
|
dev_err(&pdev->dev, "Invalid resource\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memset(&res, 0, sizeof(res));
|
||||||
|
memset(&ppd, 0, sizeof(ppd));
|
||||||
|
|
||||||
|
ppd.wait_func = bcmgenet_mii_wait;
|
||||||
|
ppd.wait_func_data = priv;
|
||||||
|
ppd.bus_name = "bcmgenet MII bus";
|
||||||
|
|
||||||
|
/* Unimac MDIO bus controller starts at UniMAC offset + MDIO_CMD
|
||||||
|
* and is 2 * 32-bits word long, 8 bytes total.
|
||||||
|
*/
|
||||||
|
res.start = pres->start + GENET_UMAC_OFF + UMAC_MDIO_CMD;
|
||||||
|
res.end = res.start + 8;
|
||||||
|
res.flags = IORESOURCE_MEM;
|
||||||
|
|
||||||
|
if (dn)
|
||||||
|
id = of_alias_get_id(dn, "eth");
|
||||||
|
else
|
||||||
|
id = pdev->id;
|
||||||
|
|
||||||
|
ppdev = platform_device_alloc(UNIMAC_MDIO_DRV_NAME, id);
|
||||||
|
if (!ppdev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Retain this platform_device pointer for later cleanup */
|
||||||
|
priv->mii_pdev = ppdev;
|
||||||
|
ppdev->dev.parent = &pdev->dev;
|
||||||
|
if (dn)
|
||||||
|
ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv);
|
||||||
|
else if (pdata)
|
||||||
|
bcmgenet_mii_pdata_init(priv, &ppd);
|
||||||
|
else
|
||||||
|
ppd.phy_mask = ~0;
|
||||||
|
|
||||||
|
ret = platform_device_add_resources(ppdev, &res, 1);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = platform_device_add(ppdev);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
platform_device_put(ppdev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_phy_interface_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
int phy_mode = device_get_phy_mode(kdev);
|
||||||
|
|
||||||
|
if (phy_mode < 0) {
|
||||||
|
dev_err(kdev, "invalid PHY mode property\n");
|
||||||
|
return phy_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->phy_interface = phy_mode;
|
||||||
|
|
||||||
|
/* We need to specifically look up whether this PHY interface is
|
||||||
|
* internal or not *before* we even try to probe the PHY driver
|
||||||
|
* over MDIO as we may have shut down the internal PHY for power
|
||||||
|
* saving purposes.
|
||||||
|
*/
|
||||||
|
if (priv->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
|
||||||
|
priv->internal_phy = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device_node *dn = priv->pdev->dev.of_node;
|
||||||
|
struct phy_device *phydev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Fetch the PHY phandle */
|
||||||
|
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
|
||||||
|
|
||||||
|
/* In the case of a fixed PHY, the DT node associated
|
||||||
|
* to the PHY is the Ethernet MAC DT node.
|
||||||
|
*/
|
||||||
|
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
|
||||||
|
ret = of_phy_register_fixed_link(dn);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->phy_dn = of_node_get(dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the link mode */
|
||||||
|
ret = bcmgenet_phy_interface_init(priv);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Make sure we initialize MoCA PHYs with a link down */
|
||||||
|
if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
|
||||||
|
phydev = of_phy_find_device(dn);
|
||||||
|
if (phydev) {
|
||||||
|
phydev->link = 0;
|
||||||
|
put_device(&phydev->mdio.dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||||
|
char phy_name[MII_BUS_ID_SIZE + 3];
|
||||||
|
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||||
|
struct phy_device *phydev;
|
||||||
|
|
||||||
|
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||||
|
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||||
|
|
||||||
|
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||||
|
snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
|
||||||
|
mdio_bus_id, pd->phy_address);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal or external PHY with MDIO access
|
||||||
|
*/
|
||||||
|
phydev = phy_attach(priv->dev, phy_name, pd->phy_interface);
|
||||||
|
if (IS_ERR(phydev)) {
|
||||||
|
dev_err(kdev, "failed to register PHY device\n");
|
||||||
|
return PTR_ERR(phydev);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* MoCA port or no MDIO access.
|
||||||
|
* Use fixed PHY to represent the link layer.
|
||||||
|
*/
|
||||||
|
struct fixed_phy_status fphy_status = {
|
||||||
|
.link = 1,
|
||||||
|
.speed = pd->phy_speed,
|
||||||
|
.duplex = pd->phy_duplex,
|
||||||
|
.pause = 0,
|
||||||
|
.asym_pause = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
|
||||||
|
if (!phydev || IS_ERR(phydev)) {
|
||||||
|
dev_err(kdev, "failed to register fixed PHY device\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we initialize MoCA PHYs with a link down */
|
||||||
|
phydev->link = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->phy_interface = pd->phy_interface;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
struct device_node *dn = kdev->of_node;
|
||||||
|
|
||||||
|
if (dn)
|
||||||
|
return bcmgenet_mii_of_init(priv);
|
||||||
|
else if (has_acpi_companion(kdev))
|
||||||
|
return bcmgenet_phy_interface_init(priv);
|
||||||
|
else
|
||||||
|
return bcmgenet_mii_pd_init(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bcmgenet_mii_init(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = bcmgenet_mii_register(priv);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = bcmgenet_mii_bus_init(priv);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
bcmgenet_mii_exit(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcmgenet_mii_exit(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
|
struct device_node *dn = priv->pdev->dev.of_node;
|
||||||
|
|
||||||
|
if (of_phy_is_fixed_link(dn))
|
||||||
|
of_phy_deregister_fixed_link(dn);
|
||||||
|
of_node_put(priv->phy_dn);
|
||||||
|
platform_device_unregister(priv->mii_pdev);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
#ifndef __UNIMAC_H
|
||||||
|
#define __UNIMAC_H
|
||||||
|
|
||||||
|
#define UMAC_HD_BKP_CTRL 0x004
|
||||||
|
#define HD_FC_EN (1 << 0)
|
||||||
|
#define HD_FC_BKOFF_OK (1 << 1)
|
||||||
|
#define IPG_CONFIG_RX_SHIFT 2
|
||||||
|
#define IPG_CONFIG_RX_MASK 0x1F
|
||||||
|
#define UMAC_CMD 0x008
|
||||||
|
#define CMD_TX_EN (1 << 0)
|
||||||
|
#define CMD_RX_EN (1 << 1)
|
||||||
|
#define CMD_SPEED_10 0
|
||||||
|
#define CMD_SPEED_100 1
|
||||||
|
#define CMD_SPEED_1000 2
|
||||||
|
#define CMD_SPEED_2500 3
|
||||||
|
#define CMD_SPEED_SHIFT 2
|
||||||
|
#define CMD_SPEED_MASK 3
|
||||||
|
#define CMD_PROMISC (1 << 4)
|
||||||
|
#define CMD_PAD_EN (1 << 5)
|
||||||
|
#define CMD_CRC_FWD (1 << 6)
|
||||||
|
#define CMD_PAUSE_FWD (1 << 7)
|
||||||
|
#define CMD_RX_PAUSE_IGNORE (1 << 8)
|
||||||
|
#define CMD_TX_ADDR_INS (1 << 9)
|
||||||
|
#define CMD_HD_EN (1 << 10)
|
||||||
|
#define CMD_SW_RESET_OLD (1 << 11)
|
||||||
|
#define CMD_SW_RESET (1 << 13)
|
||||||
|
#define CMD_LCL_LOOP_EN (1 << 15)
|
||||||
|
#define CMD_AUTO_CONFIG (1 << 22)
|
||||||
|
#define CMD_CNTL_FRM_EN (1 << 23)
|
||||||
|
#define CMD_NO_LEN_CHK (1 << 24)
|
||||||
|
#define CMD_RMT_LOOP_EN (1 << 25)
|
||||||
|
#define CMD_RX_ERR_DISC (1 << 26)
|
||||||
|
#define CMD_PRBL_EN (1 << 27)
|
||||||
|
#define CMD_TX_PAUSE_IGNORE (1 << 28)
|
||||||
|
#define CMD_TX_RX_EN (1 << 29)
|
||||||
|
#define CMD_RUNT_FILTER_DIS (1 << 30)
|
||||||
|
#define UMAC_MAC0 0x00c
|
||||||
|
#define UMAC_MAC1 0x010
|
||||||
|
#define UMAC_MAX_FRAME_LEN 0x014
|
||||||
|
#define UMAC_PAUSE_QUANTA 0x018
|
||||||
|
#define UMAC_MODE 0x044
|
||||||
|
#define MODE_LINK_STATUS (1 << 5)
|
||||||
|
#define UMAC_FRM_TAG0 0x048 /* outer tag */
|
||||||
|
#define UMAC_FRM_TAG1 0x04c /* inner tag */
|
||||||
|
#define UMAC_TX_IPG_LEN 0x05c
|
||||||
|
#define UMAC_EEE_CTRL 0x064
|
||||||
|
#define EN_LPI_RX_PAUSE (1 << 0)
|
||||||
|
#define EN_LPI_TX_PFC (1 << 1)
|
||||||
|
#define EN_LPI_TX_PAUSE (1 << 2)
|
||||||
|
#define EEE_EN (1 << 3)
|
||||||
|
#define RX_FIFO_CHECK (1 << 4)
|
||||||
|
#define EEE_TX_CLK_DIS (1 << 5)
|
||||||
|
#define DIS_EEE_10M (1 << 6)
|
||||||
|
#define LP_IDLE_PREDICTION_MODE (1 << 7)
|
||||||
|
#define UMAC_EEE_LPI_TIMER 0x068
|
||||||
|
#define UMAC_EEE_WAKE_TIMER 0x06C
|
||||||
|
#define UMAC_EEE_REF_COUNT 0x070
|
||||||
|
#define EEE_REFERENCE_COUNT_MASK 0xffff
|
||||||
|
#define UMAC_RX_IPG_INV 0x078
|
||||||
|
#define UMAC_MACSEC_PROG_TX_CRC 0x310
|
||||||
|
#define UMAC_MACSEC_CTRL 0x314
|
||||||
|
#define UMAC_PAUSE_CTRL 0x330
|
||||||
|
#define UMAC_TX_FLUSH 0x334
|
||||||
|
#define UMAC_RX_FIFO_STATUS 0x338
|
||||||
|
#define UMAC_TX_FIFO_STATUS 0x33c
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
#ifndef __UNIMAC_H
|
||||||
|
#define __UNIMAC_H
|
||||||
|
|
||||||
|
#define UMAC_HD_BKP_CTRL 0x004
|
||||||
|
#define HD_FC_EN (1 << 0)
|
||||||
|
#define HD_FC_BKOFF_OK (1 << 1)
|
||||||
|
#define IPG_CONFIG_RX_SHIFT 2
|
||||||
|
#define IPG_CONFIG_RX_MASK 0x1F
|
||||||
|
#define UMAC_CMD 0x008
|
||||||
|
#define CMD_TX_EN (1 << 0)
|
||||||
|
#define CMD_RX_EN (1 << 1)
|
||||||
|
#define CMD_SPEED_10 0
|
||||||
|
#define CMD_SPEED_100 1
|
||||||
|
#define CMD_SPEED_1000 2
|
||||||
|
#define CMD_SPEED_2500 3
|
||||||
|
#define CMD_SPEED_SHIFT 2
|
||||||
|
#define CMD_SPEED_MASK 3
|
||||||
|
#define CMD_PROMISC (1 << 4)
|
||||||
|
#define CMD_PAD_EN (1 << 5)
|
||||||
|
#define CMD_CRC_FWD (1 << 6)
|
||||||
|
#define CMD_PAUSE_FWD (1 << 7)
|
||||||
|
#define CMD_RX_PAUSE_IGNORE (1 << 8)
|
||||||
|
#define CMD_TX_ADDR_INS (1 << 9)
|
||||||
|
#define CMD_HD_EN (1 << 10)
|
||||||
|
#define CMD_SW_RESET_OLD (1 << 11)
|
||||||
|
#define CMD_SW_RESET (1 << 13)
|
||||||
|
#define CMD_LCL_LOOP_EN (1 << 15)
|
||||||
|
#define CMD_AUTO_CONFIG (1 << 22)
|
||||||
|
#define CMD_CNTL_FRM_EN (1 << 23)
|
||||||
|
#define CMD_NO_LEN_CHK (1 << 24)
|
||||||
|
#define CMD_RMT_LOOP_EN (1 << 25)
|
||||||
|
#define CMD_RX_ERR_DISC (1 << 26)
|
||||||
|
#define CMD_PRBL_EN (1 << 27)
|
||||||
|
#define CMD_TX_PAUSE_IGNORE (1 << 28)
|
||||||
|
#define CMD_TX_RX_EN (1 << 29)
|
||||||
|
#define CMD_RUNT_FILTER_DIS (1 << 30)
|
||||||
|
#define UMAC_MAC0 0x00c
|
||||||
|
#define UMAC_MAC1 0x010
|
||||||
|
#define UMAC_MAX_FRAME_LEN 0x014
|
||||||
|
#define UMAC_PAUSE_QUANTA 0x018
|
||||||
|
#define UMAC_MODE 0x044
|
||||||
|
#define MODE_LINK_STATUS (1 << 5)
|
||||||
|
#define UMAC_FRM_TAG0 0x048 /* outer tag */
|
||||||
|
#define UMAC_FRM_TAG1 0x04c /* inner tag */
|
||||||
|
#define UMAC_TX_IPG_LEN 0x05c
|
||||||
|
#define UMAC_EEE_CTRL 0x064
|
||||||
|
#define EN_LPI_RX_PAUSE (1 << 0)
|
||||||
|
#define EN_LPI_TX_PFC (1 << 1)
|
||||||
|
#define EN_LPI_TX_PAUSE (1 << 2)
|
||||||
|
#define EEE_EN (1 << 3)
|
||||||
|
#define RX_FIFO_CHECK (1 << 4)
|
||||||
|
#define EEE_TX_CLK_DIS (1 << 5)
|
||||||
|
#define DIS_EEE_10M (1 << 6)
|
||||||
|
#define LP_IDLE_PREDICTION_MODE (1 << 7)
|
||||||
|
#define UMAC_EEE_LPI_TIMER 0x068
|
||||||
|
#define UMAC_EEE_WAKE_TIMER 0x06C
|
||||||
|
#define UMAC_EEE_REF_COUNT 0x070
|
||||||
|
#define EEE_REFERENCE_COUNT_MASK 0xffff
|
||||||
|
#define UMAC_RX_IPG_INV 0x078
|
||||||
|
#define UMAC_MACSEC_PROG_TX_CRC 0x310
|
||||||
|
#define UMAC_MACSEC_CTRL 0x314
|
||||||
|
#define UMAC_PAUSE_CTRL 0x330
|
||||||
|
#define UMAC_TX_FLUSH 0x334
|
||||||
|
#define UMAC_RX_FIFO_STATUS 0x338
|
||||||
|
#define UMAC_TX_FIFO_STATUS 0x33c
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -40,18 +40,50 @@ EXTRA_DIST = \
|
||||||
e1000_82575-4.4-ethercat.h \
|
e1000_82575-4.4-ethercat.h \
|
||||||
e1000_82575-4.4-orig.c \
|
e1000_82575-4.4-orig.c \
|
||||||
e1000_82575-4.4-orig.h \
|
e1000_82575-4.4-orig.h \
|
||||||
|
e1000_82575-5.10-ethercat.c \
|
||||||
|
e1000_82575-5.10-ethercat.h \
|
||||||
|
e1000_82575-5.10-orig.c \
|
||||||
|
e1000_82575-5.10-orig.h \
|
||||||
|
e1000_82575-5.14-ethercat.c \
|
||||||
|
e1000_82575-5.14-ethercat.h \
|
||||||
|
e1000_82575-5.14-orig.c \
|
||||||
|
e1000_82575-5.14-orig.h \
|
||||||
|
e1000_82575-5.15-ethercat.c \
|
||||||
|
e1000_82575-5.15-ethercat.h \
|
||||||
|
e1000_82575-5.15-orig.c \
|
||||||
|
e1000_82575-5.15-orig.h \
|
||||||
|
e1000_82575-6.1-ethercat.c \
|
||||||
|
e1000_82575-6.1-ethercat.h \
|
||||||
|
e1000_82575-6.1-orig.c \
|
||||||
|
e1000_82575-6.1-orig.h \
|
||||||
e1000_defines-3.18-ethercat.h \
|
e1000_defines-3.18-ethercat.h \
|
||||||
e1000_defines-3.18-orig.h \
|
e1000_defines-3.18-orig.h \
|
||||||
e1000_defines-4.19-ethercat.h \
|
e1000_defines-4.19-ethercat.h \
|
||||||
e1000_defines-4.19-orig.h \
|
e1000_defines-4.19-orig.h \
|
||||||
e1000_defines-4.4-ethercat.h \
|
e1000_defines-4.4-ethercat.h \
|
||||||
e1000_defines-4.4-orig.h \
|
e1000_defines-4.4-orig.h \
|
||||||
|
e1000_defines-5.10-ethercat.h \
|
||||||
|
e1000_defines-5.10-orig.h \
|
||||||
|
e1000_defines-5.14-ethercat.h \
|
||||||
|
e1000_defines-5.14-orig.h \
|
||||||
|
e1000_defines-5.15-ethercat.h \
|
||||||
|
e1000_defines-5.15-orig.h \
|
||||||
|
e1000_defines-6.1-ethercat.h \
|
||||||
|
e1000_defines-6.1-orig.h \
|
||||||
e1000_hw-3.18-ethercat.h \
|
e1000_hw-3.18-ethercat.h \
|
||||||
e1000_hw-3.18-orig.h \
|
e1000_hw-3.18-orig.h \
|
||||||
e1000_hw-4.19-ethercat.h \
|
e1000_hw-4.19-ethercat.h \
|
||||||
e1000_hw-4.19-orig.h \
|
e1000_hw-4.19-orig.h \
|
||||||
e1000_hw-4.4-ethercat.h \
|
e1000_hw-4.4-ethercat.h \
|
||||||
e1000_hw-4.4-orig.h \
|
e1000_hw-4.4-orig.h \
|
||||||
|
e1000_hw-5.10-ethercat.h \
|
||||||
|
e1000_hw-5.10-orig.h \
|
||||||
|
e1000_hw-5.14-ethercat.h \
|
||||||
|
e1000_hw-5.14-orig.h \
|
||||||
|
e1000_hw-5.15-ethercat.h \
|
||||||
|
e1000_hw-5.15-orig.h \
|
||||||
|
e1000_hw-6.1-ethercat.h \
|
||||||
|
e1000_hw-6.1-orig.h \
|
||||||
e1000_i210-3.18-ethercat.c \
|
e1000_i210-3.18-ethercat.c \
|
||||||
e1000_i210-3.18-ethercat.h \
|
e1000_i210-3.18-ethercat.h \
|
||||||
e1000_i210-3.18-orig.c \
|
e1000_i210-3.18-orig.c \
|
||||||
|
|
@ -64,6 +96,22 @@ EXTRA_DIST = \
|
||||||
e1000_i210-4.4-ethercat.h \
|
e1000_i210-4.4-ethercat.h \
|
||||||
e1000_i210-4.4-orig.c \
|
e1000_i210-4.4-orig.c \
|
||||||
e1000_i210-4.4-orig.h \
|
e1000_i210-4.4-orig.h \
|
||||||
|
e1000_i210-5.10-ethercat.c \
|
||||||
|
e1000_i210-5.10-ethercat.h \
|
||||||
|
e1000_i210-5.10-orig.c \
|
||||||
|
e1000_i210-5.10-orig.h \
|
||||||
|
e1000_i210-5.14-ethercat.c \
|
||||||
|
e1000_i210-5.14-ethercat.h \
|
||||||
|
e1000_i210-5.14-orig.c \
|
||||||
|
e1000_i210-5.14-orig.h \
|
||||||
|
e1000_i210-5.15-ethercat.c \
|
||||||
|
e1000_i210-5.15-ethercat.h \
|
||||||
|
e1000_i210-5.15-orig.c \
|
||||||
|
e1000_i210-5.15-orig.h \
|
||||||
|
e1000_i210-6.1-ethercat.c \
|
||||||
|
e1000_i210-6.1-ethercat.h \
|
||||||
|
e1000_i210-6.1-orig.c \
|
||||||
|
e1000_i210-6.1-orig.h \
|
||||||
e1000_mac-3.18-ethercat.c \
|
e1000_mac-3.18-ethercat.c \
|
||||||
e1000_mac-3.18-ethercat.h \
|
e1000_mac-3.18-ethercat.h \
|
||||||
e1000_mac-3.18-orig.c \
|
e1000_mac-3.18-orig.c \
|
||||||
|
|
@ -76,6 +124,22 @@ EXTRA_DIST = \
|
||||||
e1000_mac-4.4-ethercat.h \
|
e1000_mac-4.4-ethercat.h \
|
||||||
e1000_mac-4.4-orig.c \
|
e1000_mac-4.4-orig.c \
|
||||||
e1000_mac-4.4-orig.h \
|
e1000_mac-4.4-orig.h \
|
||||||
|
e1000_mac-5.10-ethercat.c \
|
||||||
|
e1000_mac-5.10-ethercat.h \
|
||||||
|
e1000_mac-5.10-orig.c \
|
||||||
|
e1000_mac-5.10-orig.h \
|
||||||
|
e1000_mac-5.14-ethercat.c \
|
||||||
|
e1000_mac-5.14-ethercat.h \
|
||||||
|
e1000_mac-5.14-orig.c \
|
||||||
|
e1000_mac-5.14-orig.h \
|
||||||
|
e1000_mac-5.15-ethercat.c \
|
||||||
|
e1000_mac-5.15-ethercat.h \
|
||||||
|
e1000_mac-5.15-orig.c \
|
||||||
|
e1000_mac-5.15-orig.h \
|
||||||
|
e1000_mac-6.1-ethercat.c \
|
||||||
|
e1000_mac-6.1-ethercat.h \
|
||||||
|
e1000_mac-6.1-orig.c \
|
||||||
|
e1000_mac-6.1-orig.h \
|
||||||
e1000_mbx-3.18-ethercat.c \
|
e1000_mbx-3.18-ethercat.c \
|
||||||
e1000_mbx-3.18-ethercat.h \
|
e1000_mbx-3.18-ethercat.h \
|
||||||
e1000_mbx-3.18-orig.c \
|
e1000_mbx-3.18-orig.c \
|
||||||
|
|
@ -88,6 +152,22 @@ EXTRA_DIST = \
|
||||||
e1000_mbx-4.4-ethercat.h \
|
e1000_mbx-4.4-ethercat.h \
|
||||||
e1000_mbx-4.4-orig.c \
|
e1000_mbx-4.4-orig.c \
|
||||||
e1000_mbx-4.4-orig.h \
|
e1000_mbx-4.4-orig.h \
|
||||||
|
e1000_mbx-5.10-ethercat.c \
|
||||||
|
e1000_mbx-5.10-ethercat.h \
|
||||||
|
e1000_mbx-5.10-orig.c \
|
||||||
|
e1000_mbx-5.10-orig.h \
|
||||||
|
e1000_mbx-5.14-ethercat.c \
|
||||||
|
e1000_mbx-5.14-ethercat.h \
|
||||||
|
e1000_mbx-5.14-orig.c \
|
||||||
|
e1000_mbx-5.14-orig.h \
|
||||||
|
e1000_mbx-5.15-ethercat.c \
|
||||||
|
e1000_mbx-5.15-ethercat.h \
|
||||||
|
e1000_mbx-5.15-orig.c \
|
||||||
|
e1000_mbx-5.15-orig.h \
|
||||||
|
e1000_mbx-6.1-ethercat.c \
|
||||||
|
e1000_mbx-6.1-ethercat.h \
|
||||||
|
e1000_mbx-6.1-orig.c \
|
||||||
|
e1000_mbx-6.1-orig.h \
|
||||||
e1000_nvm-3.18-ethercat.c \
|
e1000_nvm-3.18-ethercat.c \
|
||||||
e1000_nvm-3.18-ethercat.h \
|
e1000_nvm-3.18-ethercat.h \
|
||||||
e1000_nvm-3.18-orig.c \
|
e1000_nvm-3.18-orig.c \
|
||||||
|
|
@ -100,6 +180,22 @@ EXTRA_DIST = \
|
||||||
e1000_nvm-4.4-ethercat.h \
|
e1000_nvm-4.4-ethercat.h \
|
||||||
e1000_nvm-4.4-orig.c \
|
e1000_nvm-4.4-orig.c \
|
||||||
e1000_nvm-4.4-orig.h \
|
e1000_nvm-4.4-orig.h \
|
||||||
|
e1000_nvm-5.10-ethercat.c \
|
||||||
|
e1000_nvm-5.10-ethercat.h \
|
||||||
|
e1000_nvm-5.10-orig.c \
|
||||||
|
e1000_nvm-5.10-orig.h \
|
||||||
|
e1000_nvm-5.14-ethercat.c \
|
||||||
|
e1000_nvm-5.14-ethercat.h \
|
||||||
|
e1000_nvm-5.14-orig.c \
|
||||||
|
e1000_nvm-5.14-orig.h \
|
||||||
|
e1000_nvm-5.15-ethercat.c \
|
||||||
|
e1000_nvm-5.15-ethercat.h \
|
||||||
|
e1000_nvm-5.15-orig.c \
|
||||||
|
e1000_nvm-5.15-orig.h \
|
||||||
|
e1000_nvm-6.1-ethercat.c \
|
||||||
|
e1000_nvm-6.1-ethercat.h \
|
||||||
|
e1000_nvm-6.1-orig.c \
|
||||||
|
e1000_nvm-6.1-orig.h \
|
||||||
e1000_phy-3.18-ethercat.c \
|
e1000_phy-3.18-ethercat.c \
|
||||||
e1000_phy-3.18-ethercat.h \
|
e1000_phy-3.18-ethercat.h \
|
||||||
e1000_phy-3.18-orig.c \
|
e1000_phy-3.18-orig.c \
|
||||||
|
|
@ -112,42 +208,106 @@ EXTRA_DIST = \
|
||||||
e1000_phy-4.4-ethercat.h \
|
e1000_phy-4.4-ethercat.h \
|
||||||
e1000_phy-4.4-orig.c \
|
e1000_phy-4.4-orig.c \
|
||||||
e1000_phy-4.4-orig.h \
|
e1000_phy-4.4-orig.h \
|
||||||
|
e1000_phy-5.10-ethercat.c \
|
||||||
|
e1000_phy-5.10-ethercat.h \
|
||||||
|
e1000_phy-5.10-orig.c \
|
||||||
|
e1000_phy-5.10-orig.h \
|
||||||
|
e1000_phy-5.14-ethercat.c \
|
||||||
|
e1000_phy-5.14-ethercat.h \
|
||||||
|
e1000_phy-5.14-orig.c \
|
||||||
|
e1000_phy-5.14-orig.h \
|
||||||
|
e1000_phy-5.15-ethercat.c \
|
||||||
|
e1000_phy-5.15-ethercat.h \
|
||||||
|
e1000_phy-5.15-orig.c \
|
||||||
|
e1000_phy-5.15-orig.h \
|
||||||
|
e1000_phy-6.1-ethercat.c \
|
||||||
|
e1000_phy-6.1-ethercat.h \
|
||||||
|
e1000_phy-6.1-orig.c \
|
||||||
|
e1000_phy-6.1-orig.h \
|
||||||
e1000_regs-3.18-ethercat.h \
|
e1000_regs-3.18-ethercat.h \
|
||||||
e1000_regs-3.18-orig.h \
|
e1000_regs-3.18-orig.h \
|
||||||
e1000_regs-4.19-ethercat.h \
|
e1000_regs-4.19-ethercat.h \
|
||||||
e1000_regs-4.19-orig.h \
|
e1000_regs-4.19-orig.h \
|
||||||
e1000_regs-4.4-ethercat.h \
|
e1000_regs-4.4-ethercat.h \
|
||||||
e1000_regs-4.4-orig.h \
|
e1000_regs-4.4-orig.h \
|
||||||
|
e1000_regs-5.10-ethercat.h \
|
||||||
|
e1000_regs-5.10-orig.h \
|
||||||
|
e1000_regs-5.14-ethercat.h \
|
||||||
|
e1000_regs-5.14-orig.h \
|
||||||
|
e1000_regs-5.15-ethercat.h \
|
||||||
|
e1000_regs-5.15-orig.h \
|
||||||
|
e1000_regs-6.1-ethercat.h \
|
||||||
|
e1000_regs-6.1-orig.h \
|
||||||
igb-3.18-ethercat.h \
|
igb-3.18-ethercat.h \
|
||||||
igb-3.18-orig.h \
|
igb-3.18-orig.h \
|
||||||
igb-4.19-ethercat.h \
|
igb-4.19-ethercat.h \
|
||||||
igb-4.19-orig.h \
|
igb-4.19-orig.h \
|
||||||
igb-4.4-ethercat.h \
|
igb-4.4-ethercat.h \
|
||||||
igb-4.4-orig.h \
|
igb-4.4-orig.h \
|
||||||
|
igb-5.10-ethercat.h \
|
||||||
|
igb-5.10-orig.h \
|
||||||
|
igb-5.14-ethercat.h \
|
||||||
|
igb-5.14-orig.h \
|
||||||
|
igb-5.15-ethercat.h \
|
||||||
|
igb-5.15-orig.h \
|
||||||
|
igb-6.1-ethercat.h \
|
||||||
|
igb-6.1-orig.h \
|
||||||
igb_ethtool-3.18-ethercat.c \
|
igb_ethtool-3.18-ethercat.c \
|
||||||
igb_ethtool-3.18-orig.c \
|
igb_ethtool-3.18-orig.c \
|
||||||
igb_ethtool-4.19-ethercat.c \
|
igb_ethtool-4.19-ethercat.c \
|
||||||
igb_ethtool-4.19-orig.c \
|
igb_ethtool-4.19-orig.c \
|
||||||
igb_ethtool-4.4-ethercat.c \
|
igb_ethtool-4.4-ethercat.c \
|
||||||
igb_ethtool-4.4-orig.c \
|
igb_ethtool-4.4-orig.c \
|
||||||
|
igb_ethtool-5.10-ethercat.c \
|
||||||
|
igb_ethtool-5.10-orig.c \
|
||||||
|
igb_ethtool-5.14-ethercat.c \
|
||||||
|
igb_ethtool-5.14-orig.c \
|
||||||
|
igb_ethtool-5.15-ethercat.c \
|
||||||
|
igb_ethtool-5.15-orig.c \
|
||||||
|
igb_ethtool-6.1-ethercat.c \
|
||||||
|
igb_ethtool-6.1-orig.c \
|
||||||
igb_hwmon-3.18-ethercat.c \
|
igb_hwmon-3.18-ethercat.c \
|
||||||
igb_hwmon-3.18-orig.c \
|
igb_hwmon-3.18-orig.c \
|
||||||
igb_hwmon-4.19-ethercat.c \
|
igb_hwmon-4.19-ethercat.c \
|
||||||
igb_hwmon-4.19-orig.c \
|
igb_hwmon-4.19-orig.c \
|
||||||
igb_hwmon-4.4-ethercat.c \
|
igb_hwmon-4.4-ethercat.c \
|
||||||
igb_hwmon-4.4-orig.c \
|
igb_hwmon-4.4-orig.c \
|
||||||
|
igb_hwmon-5.10-ethercat.c \
|
||||||
|
igb_hwmon-5.10-orig.c \
|
||||||
|
igb_hwmon-5.14-ethercat.c \
|
||||||
|
igb_hwmon-5.14-orig.c \
|
||||||
|
igb_hwmon-5.15-ethercat.c \
|
||||||
|
igb_hwmon-5.15-orig.c \
|
||||||
|
igb_hwmon-6.1-ethercat.c \
|
||||||
|
igb_hwmon-6.1-orig.c \
|
||||||
igb_main-3.18-ethercat.c \
|
igb_main-3.18-ethercat.c \
|
||||||
igb_main-3.18-orig.c \
|
igb_main-3.18-orig.c \
|
||||||
igb_main-4.19-ethercat.c \
|
igb_main-4.19-ethercat.c \
|
||||||
igb_main-4.19-orig.c \
|
igb_main-4.19-orig.c \
|
||||||
igb_main-4.4-ethercat.c \
|
igb_main-4.4-ethercat.c \
|
||||||
igb_main-4.4-orig.c \
|
igb_main-4.4-orig.c \
|
||||||
|
igb_main-5.10-ethercat.c \
|
||||||
|
igb_main-5.10-orig.c \
|
||||||
|
igb_main-5.14-ethercat.c \
|
||||||
|
igb_main-5.14-orig.c \
|
||||||
|
igb_main-5.15-ethercat.c \
|
||||||
|
igb_main-5.15-orig.c \
|
||||||
|
igb_main-6.1-ethercat.c \
|
||||||
|
igb_main-6.1-orig.c \
|
||||||
igb_ptp-3.18-ethercat.c \
|
igb_ptp-3.18-ethercat.c \
|
||||||
igb_ptp-3.18-orig.c \
|
igb_ptp-3.18-orig.c \
|
||||||
igb_ptp-4.19-ethercat.c \
|
igb_ptp-4.19-ethercat.c \
|
||||||
igb_ptp-4.19-orig.c \
|
igb_ptp-4.19-orig.c \
|
||||||
igb_ptp-4.4-ethercat.c \
|
igb_ptp-4.4-ethercat.c \
|
||||||
igb_ptp-4.4-orig.c \
|
igb_ptp-4.4-orig.c \
|
||||||
|
igb_ptp-5.10-ethercat.c \
|
||||||
|
igb_ptp-5.10-orig.c \
|
||||||
|
igb_ptp-5.14-ethercat.c \
|
||||||
|
igb_ptp-5.14-orig.c \
|
||||||
|
igb_ptp-5.15-ethercat.c \
|
||||||
|
igb_ptp-5.15-orig.c \
|
||||||
|
igb_ptp-6.1-ethercat.c \
|
||||||
|
igb_ptp-6.1-orig.c \
|
||||||
update.sh
|
update.sh
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,554 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||||
|
|
||||||
|
#ifndef _E1000_IGB_HW_H_
|
||||||
|
#define _E1000_IGB_HW_H_
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
|
#include "e1000_regs.h"
|
||||||
|
#include "e1000_defines.h"
|
||||||
|
|
||||||
|
struct e1000_hw;
|
||||||
|
|
||||||
|
#define E1000_DEV_ID_82576 0x10C9
|
||||||
|
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||||
|
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||||
|
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
|
||||||
|
#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
|
||||||
|
#define E1000_DEV_ID_82576_NS 0x150A
|
||||||
|
#define E1000_DEV_ID_82576_NS_SERDES 0x1518
|
||||||
|
#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
|
||||||
|
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
|
||||||
|
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
|
||||||
|
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
|
||||||
|
#define E1000_DEV_ID_82580_COPPER 0x150E
|
||||||
|
#define E1000_DEV_ID_82580_FIBER 0x150F
|
||||||
|
#define E1000_DEV_ID_82580_SERDES 0x1510
|
||||||
|
#define E1000_DEV_ID_82580_SGMII 0x1511
|
||||||
|
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
|
||||||
|
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
|
||||||
|
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
|
||||||
|
#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
|
||||||
|
#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
|
||||||
|
#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
|
||||||
|
#define E1000_DEV_ID_I350_COPPER 0x1521
|
||||||
|
#define E1000_DEV_ID_I350_FIBER 0x1522
|
||||||
|
#define E1000_DEV_ID_I350_SERDES 0x1523
|
||||||
|
#define E1000_DEV_ID_I350_SGMII 0x1524
|
||||||
|
#define E1000_DEV_ID_I210_COPPER 0x1533
|
||||||
|
#define E1000_DEV_ID_I210_FIBER 0x1536
|
||||||
|
#define E1000_DEV_ID_I210_SERDES 0x1537
|
||||||
|
#define E1000_DEV_ID_I210_SGMII 0x1538
|
||||||
|
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
|
||||||
|
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
|
||||||
|
#define E1000_DEV_ID_I211_COPPER 0x1539
|
||||||
|
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
|
||||||
|
#define E1000_DEV_ID_I354_SGMII 0x1F41
|
||||||
|
#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45
|
||||||
|
|
||||||
|
#define E1000_REVISION_2 2
|
||||||
|
#define E1000_REVISION_4 4
|
||||||
|
|
||||||
|
#define E1000_FUNC_0 0
|
||||||
|
#define E1000_FUNC_1 1
|
||||||
|
#define E1000_FUNC_2 2
|
||||||
|
#define E1000_FUNC_3 3
|
||||||
|
|
||||||
|
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
|
||||||
|
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
|
||||||
|
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
|
||||||
|
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
|
||||||
|
|
||||||
|
enum e1000_mac_type {
|
||||||
|
e1000_undefined = 0,
|
||||||
|
e1000_82575,
|
||||||
|
e1000_82576,
|
||||||
|
e1000_82580,
|
||||||
|
e1000_i350,
|
||||||
|
e1000_i354,
|
||||||
|
e1000_i210,
|
||||||
|
e1000_i211,
|
||||||
|
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_media_type {
|
||||||
|
e1000_media_type_unknown = 0,
|
||||||
|
e1000_media_type_copper = 1,
|
||||||
|
e1000_media_type_fiber = 2,
|
||||||
|
e1000_media_type_internal_serdes = 3,
|
||||||
|
e1000_num_media_types
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_nvm_type {
|
||||||
|
e1000_nvm_unknown = 0,
|
||||||
|
e1000_nvm_none,
|
||||||
|
e1000_nvm_eeprom_spi,
|
||||||
|
e1000_nvm_flash_hw,
|
||||||
|
e1000_nvm_invm,
|
||||||
|
e1000_nvm_flash_sw
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_nvm_override {
|
||||||
|
e1000_nvm_override_none = 0,
|
||||||
|
e1000_nvm_override_spi_small,
|
||||||
|
e1000_nvm_override_spi_large,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_phy_type {
|
||||||
|
e1000_phy_unknown = 0,
|
||||||
|
e1000_phy_none,
|
||||||
|
e1000_phy_m88,
|
||||||
|
e1000_phy_igp,
|
||||||
|
e1000_phy_igp_2,
|
||||||
|
e1000_phy_gg82563,
|
||||||
|
e1000_phy_igp_3,
|
||||||
|
e1000_phy_ife,
|
||||||
|
e1000_phy_82580,
|
||||||
|
e1000_phy_i210,
|
||||||
|
e1000_phy_bcm54616,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_bus_type {
|
||||||
|
e1000_bus_type_unknown = 0,
|
||||||
|
e1000_bus_type_pci,
|
||||||
|
e1000_bus_type_pcix,
|
||||||
|
e1000_bus_type_pci_express,
|
||||||
|
e1000_bus_type_reserved
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_bus_speed {
|
||||||
|
e1000_bus_speed_unknown = 0,
|
||||||
|
e1000_bus_speed_33,
|
||||||
|
e1000_bus_speed_66,
|
||||||
|
e1000_bus_speed_100,
|
||||||
|
e1000_bus_speed_120,
|
||||||
|
e1000_bus_speed_133,
|
||||||
|
e1000_bus_speed_2500,
|
||||||
|
e1000_bus_speed_5000,
|
||||||
|
e1000_bus_speed_reserved
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_bus_width {
|
||||||
|
e1000_bus_width_unknown = 0,
|
||||||
|
e1000_bus_width_pcie_x1,
|
||||||
|
e1000_bus_width_pcie_x2,
|
||||||
|
e1000_bus_width_pcie_x4 = 4,
|
||||||
|
e1000_bus_width_pcie_x8 = 8,
|
||||||
|
e1000_bus_width_32,
|
||||||
|
e1000_bus_width_64,
|
||||||
|
e1000_bus_width_reserved
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_1000t_rx_status {
|
||||||
|
e1000_1000t_rx_status_not_ok = 0,
|
||||||
|
e1000_1000t_rx_status_ok,
|
||||||
|
e1000_1000t_rx_status_undefined = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_rev_polarity {
|
||||||
|
e1000_rev_polarity_normal = 0,
|
||||||
|
e1000_rev_polarity_reversed,
|
||||||
|
e1000_rev_polarity_undefined = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e1000_fc_mode {
|
||||||
|
e1000_fc_none = 0,
|
||||||
|
e1000_fc_rx_pause,
|
||||||
|
e1000_fc_tx_pause,
|
||||||
|
e1000_fc_full,
|
||||||
|
e1000_fc_default = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Statistics counters collected by the MAC */
|
||||||
|
struct e1000_hw_stats {
|
||||||
|
u64 crcerrs;
|
||||||
|
u64 algnerrc;
|
||||||
|
u64 symerrs;
|
||||||
|
u64 rxerrc;
|
||||||
|
u64 mpc;
|
||||||
|
u64 scc;
|
||||||
|
u64 ecol;
|
||||||
|
u64 mcc;
|
||||||
|
u64 latecol;
|
||||||
|
u64 colc;
|
||||||
|
u64 dc;
|
||||||
|
u64 tncrs;
|
||||||
|
u64 sec;
|
||||||
|
u64 cexterr;
|
||||||
|
u64 rlec;
|
||||||
|
u64 xonrxc;
|
||||||
|
u64 xontxc;
|
||||||
|
u64 xoffrxc;
|
||||||
|
u64 xofftxc;
|
||||||
|
u64 fcruc;
|
||||||
|
u64 prc64;
|
||||||
|
u64 prc127;
|
||||||
|
u64 prc255;
|
||||||
|
u64 prc511;
|
||||||
|
u64 prc1023;
|
||||||
|
u64 prc1522;
|
||||||
|
u64 gprc;
|
||||||
|
u64 bprc;
|
||||||
|
u64 mprc;
|
||||||
|
u64 gptc;
|
||||||
|
u64 gorc;
|
||||||
|
u64 gotc;
|
||||||
|
u64 rnbc;
|
||||||
|
u64 ruc;
|
||||||
|
u64 rfc;
|
||||||
|
u64 roc;
|
||||||
|
u64 rjc;
|
||||||
|
u64 mgprc;
|
||||||
|
u64 mgpdc;
|
||||||
|
u64 mgptc;
|
||||||
|
u64 tor;
|
||||||
|
u64 tot;
|
||||||
|
u64 tpr;
|
||||||
|
u64 tpt;
|
||||||
|
u64 ptc64;
|
||||||
|
u64 ptc127;
|
||||||
|
u64 ptc255;
|
||||||
|
u64 ptc511;
|
||||||
|
u64 ptc1023;
|
||||||
|
u64 ptc1522;
|
||||||
|
u64 mptc;
|
||||||
|
u64 bptc;
|
||||||
|
u64 tsctc;
|
||||||
|
u64 tsctfc;
|
||||||
|
u64 iac;
|
||||||
|
u64 icrxptc;
|
||||||
|
u64 icrxatc;
|
||||||
|
u64 ictxptc;
|
||||||
|
u64 ictxatc;
|
||||||
|
u64 ictxqec;
|
||||||
|
u64 ictxqmtc;
|
||||||
|
u64 icrxdmtc;
|
||||||
|
u64 icrxoc;
|
||||||
|
u64 cbtmpc;
|
||||||
|
u64 htdpmc;
|
||||||
|
u64 cbrdpc;
|
||||||
|
u64 cbrmpc;
|
||||||
|
u64 rpthc;
|
||||||
|
u64 hgptc;
|
||||||
|
u64 htcbdpc;
|
||||||
|
u64 hgorc;
|
||||||
|
u64 hgotc;
|
||||||
|
u64 lenerrs;
|
||||||
|
u64 scvpc;
|
||||||
|
u64 hrmpc;
|
||||||
|
u64 doosync;
|
||||||
|
u64 o2bgptc;
|
||||||
|
u64 o2bspc;
|
||||||
|
u64 b2ospc;
|
||||||
|
u64 b2ogprc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_host_mng_dhcp_cookie {
|
||||||
|
u32 signature;
|
||||||
|
u8 status;
|
||||||
|
u8 reserved0;
|
||||||
|
u16 vlan_id;
|
||||||
|
u32 reserved1;
|
||||||
|
u16 reserved2;
|
||||||
|
u8 reserved3;
|
||||||
|
u8 checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Host Interface "Rev 1" */
|
||||||
|
struct e1000_host_command_header {
|
||||||
|
u8 command_id;
|
||||||
|
u8 command_length;
|
||||||
|
u8 command_options;
|
||||||
|
u8 checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_HI_MAX_DATA_LENGTH 252
|
||||||
|
struct e1000_host_command_info {
|
||||||
|
struct e1000_host_command_header command_header;
|
||||||
|
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Host Interface "Rev 2" */
|
||||||
|
struct e1000_host_mng_command_header {
|
||||||
|
u8 command_id;
|
||||||
|
u8 checksum;
|
||||||
|
u16 reserved1;
|
||||||
|
u16 reserved2;
|
||||||
|
u16 command_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
|
||||||
|
struct e1000_host_mng_command_info {
|
||||||
|
struct e1000_host_mng_command_header command_header;
|
||||||
|
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "e1000_mac.h"
|
||||||
|
#include "e1000_phy.h"
|
||||||
|
#include "e1000_nvm.h"
|
||||||
|
#include "e1000_mbx.h"
|
||||||
|
|
||||||
|
struct e1000_mac_operations {
|
||||||
|
s32 (*check_for_link)(struct e1000_hw *);
|
||||||
|
s32 (*reset_hw)(struct e1000_hw *);
|
||||||
|
s32 (*init_hw)(struct e1000_hw *);
|
||||||
|
bool (*check_mng_mode)(struct e1000_hw *);
|
||||||
|
s32 (*setup_physical_interface)(struct e1000_hw *);
|
||||||
|
void (*rar_set)(struct e1000_hw *, u8 *, u32);
|
||||||
|
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||||
|
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
|
||||||
|
s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
|
||||||
|
void (*release_swfw_sync)(struct e1000_hw *, u16);
|
||||||
|
#ifdef CONFIG_IGB_HWMON
|
||||||
|
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
|
||||||
|
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
|
||||||
|
#endif
|
||||||
|
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_phy_operations {
|
||||||
|
s32 (*acquire)(struct e1000_hw *);
|
||||||
|
s32 (*check_polarity)(struct e1000_hw *);
|
||||||
|
s32 (*check_reset_block)(struct e1000_hw *);
|
||||||
|
s32 (*force_speed_duplex)(struct e1000_hw *);
|
||||||
|
s32 (*get_cfg_done)(struct e1000_hw *hw);
|
||||||
|
s32 (*get_cable_length)(struct e1000_hw *);
|
||||||
|
s32 (*get_phy_info)(struct e1000_hw *);
|
||||||
|
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
|
||||||
|
void (*release)(struct e1000_hw *);
|
||||||
|
s32 (*reset)(struct e1000_hw *);
|
||||||
|
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
|
||||||
|
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
|
||||||
|
s32 (*write_reg)(struct e1000_hw *, u32, u16);
|
||||||
|
s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
|
||||||
|
s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_nvm_operations {
|
||||||
|
s32 (*acquire)(struct e1000_hw *);
|
||||||
|
s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
|
||||||
|
void (*release)(struct e1000_hw *);
|
||||||
|
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
|
||||||
|
s32 (*update)(struct e1000_hw *);
|
||||||
|
s32 (*validate)(struct e1000_hw *);
|
||||||
|
s32 (*valid_led_default)(struct e1000_hw *, u16 *);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E1000_MAX_SENSORS 3
|
||||||
|
|
||||||
|
struct e1000_thermal_diode_data {
|
||||||
|
u8 location;
|
||||||
|
u8 temp;
|
||||||
|
u8 caution_thresh;
|
||||||
|
u8 max_op_thresh;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_thermal_sensor_data {
|
||||||
|
struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_info {
|
||||||
|
s32 (*get_invariants)(struct e1000_hw *);
|
||||||
|
struct e1000_mac_operations *mac_ops;
|
||||||
|
const struct e1000_phy_operations *phy_ops;
|
||||||
|
struct e1000_nvm_operations *nvm_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct e1000_info e1000_82575_info;
|
||||||
|
|
||||||
|
struct e1000_mac_info {
|
||||||
|
struct e1000_mac_operations ops;
|
||||||
|
|
||||||
|
u8 addr[6];
|
||||||
|
u8 perm_addr[6];
|
||||||
|
|
||||||
|
enum e1000_mac_type type;
|
||||||
|
|
||||||
|
u32 ledctl_default;
|
||||||
|
u32 ledctl_mode1;
|
||||||
|
u32 ledctl_mode2;
|
||||||
|
u32 mc_filter_type;
|
||||||
|
u32 txcw;
|
||||||
|
|
||||||
|
u16 mta_reg_count;
|
||||||
|
u16 uta_reg_count;
|
||||||
|
|
||||||
|
/* Maximum size of the MTA register table in all supported adapters */
|
||||||
|
#define MAX_MTA_REG 128
|
||||||
|
u32 mta_shadow[MAX_MTA_REG];
|
||||||
|
u16 rar_entry_count;
|
||||||
|
|
||||||
|
u8 forced_speed_duplex;
|
||||||
|
|
||||||
|
bool adaptive_ifs;
|
||||||
|
bool arc_subsystem_valid;
|
||||||
|
bool asf_firmware_present;
|
||||||
|
bool autoneg;
|
||||||
|
bool autoneg_failed;
|
||||||
|
bool disable_hw_init_bits;
|
||||||
|
bool get_link_status;
|
||||||
|
bool ifs_params_forced;
|
||||||
|
bool in_ifs_mode;
|
||||||
|
bool report_tx_early;
|
||||||
|
bool serdes_has_link;
|
||||||
|
bool tx_pkt_filtering;
|
||||||
|
struct e1000_thermal_sensor_data thermal_sensor_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_phy_info {
|
||||||
|
struct e1000_phy_operations ops;
|
||||||
|
|
||||||
|
enum e1000_phy_type type;
|
||||||
|
|
||||||
|
enum e1000_1000t_rx_status local_rx;
|
||||||
|
enum e1000_1000t_rx_status remote_rx;
|
||||||
|
enum e1000_ms_type ms_type;
|
||||||
|
enum e1000_ms_type original_ms_type;
|
||||||
|
enum e1000_rev_polarity cable_polarity;
|
||||||
|
enum e1000_smart_speed smart_speed;
|
||||||
|
|
||||||
|
u32 addr;
|
||||||
|
u32 id;
|
||||||
|
u32 reset_delay_us; /* in usec */
|
||||||
|
u32 revision;
|
||||||
|
|
||||||
|
enum e1000_media_type media_type;
|
||||||
|
|
||||||
|
u16 autoneg_advertised;
|
||||||
|
u16 autoneg_mask;
|
||||||
|
u16 cable_length;
|
||||||
|
u16 max_cable_length;
|
||||||
|
u16 min_cable_length;
|
||||||
|
u16 pair_length[4];
|
||||||
|
|
||||||
|
u8 mdix;
|
||||||
|
|
||||||
|
bool disable_polarity_correction;
|
||||||
|
bool is_mdix;
|
||||||
|
bool polarity_correction;
|
||||||
|
bool reset_disable;
|
||||||
|
bool speed_downgraded;
|
||||||
|
bool autoneg_wait_to_complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_nvm_info {
|
||||||
|
struct e1000_nvm_operations ops;
|
||||||
|
enum e1000_nvm_type type;
|
||||||
|
enum e1000_nvm_override override;
|
||||||
|
|
||||||
|
u32 flash_bank_size;
|
||||||
|
u32 flash_base_addr;
|
||||||
|
|
||||||
|
u16 word_size;
|
||||||
|
u16 delay_usec;
|
||||||
|
u16 address_bits;
|
||||||
|
u16 opcode_bits;
|
||||||
|
u16 page_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_bus_info {
|
||||||
|
enum e1000_bus_type type;
|
||||||
|
enum e1000_bus_speed speed;
|
||||||
|
enum e1000_bus_width width;
|
||||||
|
|
||||||
|
u32 snoop;
|
||||||
|
|
||||||
|
u16 func;
|
||||||
|
u16 pci_cmd_word;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_fc_info {
|
||||||
|
u32 high_water; /* Flow control high-water mark */
|
||||||
|
u32 low_water; /* Flow control low-water mark */
|
||||||
|
u16 pause_time; /* Flow control pause timer */
|
||||||
|
bool send_xon; /* Flow control send XON */
|
||||||
|
bool strict_ieee; /* Strict IEEE mode */
|
||||||
|
enum e1000_fc_mode current_mode; /* Type of flow control */
|
||||||
|
enum e1000_fc_mode requested_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_mbx_operations {
|
||||||
|
s32 (*init_params)(struct e1000_hw *hw);
|
||||||
|
s32 (*read)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||||
|
bool unlock);
|
||||||
|
s32 (*write)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||||
|
s32 (*read_posted)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||||
|
s32 (*write_posted)(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||||
|
u16 mbx_id);
|
||||||
|
s32 (*check_for_msg)(struct e1000_hw *hw, u16 mbx_id);
|
||||||
|
s32 (*check_for_ack)(struct e1000_hw *hw, u16 mbx_id);
|
||||||
|
s32 (*check_for_rst)(struct e1000_hw *hw, u16 mbx_id);
|
||||||
|
s32 (*unlock)(struct e1000_hw *hw, u16 mbx_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_mbx_stats {
|
||||||
|
u32 msgs_tx;
|
||||||
|
u32 msgs_rx;
|
||||||
|
|
||||||
|
u32 acks;
|
||||||
|
u32 reqs;
|
||||||
|
u32 rsts;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_mbx_info {
|
||||||
|
struct e1000_mbx_operations ops;
|
||||||
|
struct e1000_mbx_stats stats;
|
||||||
|
u32 timeout;
|
||||||
|
u32 usec_delay;
|
||||||
|
u16 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_dev_spec_82575 {
|
||||||
|
bool sgmii_active;
|
||||||
|
bool global_device_reset;
|
||||||
|
bool eee_disable;
|
||||||
|
bool clear_semaphore_once;
|
||||||
|
struct e1000_sfp_flags eth_flags;
|
||||||
|
bool module_plugged;
|
||||||
|
u8 media_port;
|
||||||
|
bool media_changed;
|
||||||
|
bool mas_capable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct e1000_hw {
|
||||||
|
void *back;
|
||||||
|
|
||||||
|
u8 __iomem *hw_addr;
|
||||||
|
u8 __iomem *flash_address;
|
||||||
|
unsigned long io_base;
|
||||||
|
|
||||||
|
struct e1000_mac_info mac;
|
||||||
|
struct e1000_fc_info fc;
|
||||||
|
struct e1000_phy_info phy;
|
||||||
|
struct e1000_nvm_info nvm;
|
||||||
|
struct e1000_bus_info bus;
|
||||||
|
struct e1000_mbx_info mbx;
|
||||||
|
struct e1000_host_mng_dhcp_cookie mng_cookie;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct e1000_dev_spec_82575 _82575;
|
||||||
|
} dev_spec;
|
||||||
|
|
||||||
|
u16 device_id;
|
||||||
|
u16 subsystem_vendor_id;
|
||||||
|
u16 subsystem_device_id;
|
||||||
|
u16 vendor_id;
|
||||||
|
|
||||||
|
u8 revision_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_device *igb_get_hw_dev(struct e1000_hw *hw);
|
||||||
|
#define hw_dbg(format, arg...) \
|
||||||
|
netdev_dbg(igb_get_hw_dev(hw), format, ##arg)
|
||||||
|
|
||||||
|
/* These functions must be implemented by drivers */
|
||||||
|
s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||||
|
s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||||
|
|
||||||
|
void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||||
|
void igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||||
|
#endif /* _E1000_IGB_HW_H_ */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue