OpenNetVM mTCP Module Code Cleanup (#4)
This change updates mTCP from their master branch and cleans up the OpenNetVM module. The ONVM module is reorganized to match the DPDK module. This includes: - Removed the command line arguments for running epserver + This removes the extra arg passing between methods + Moved the ONVM arguments to `epserver.conf` - Added configure options to build mtcp with the ONVM library - Added preprocessor macros to build ONVM specific code on-demand Commit log: * - IP defrag module for dpdk integrated (partly derived from ip_reassembly/ example code). -> Currently disabled... because I need some testing suite that can fragment IP datagrams - Cleaned up the Makefile.in scripts. * - Fixed an ICMP-related bug that was accidentally introduced when hw-chksumming was implemented. - Cleaned up the Makefile.in script - Cleaned up dpdk_module.c file. * - Applied fixes for suspect snippets identified by Coverity. - Added IP_DEFRAG warning. * - More fixes. * Adding coverity badge. - Needs more code fixing :S * - Minor fixes. * - Minor error checks. * - More & more fixes. * - Forgot to check in these files. * - More error checking. * - Added more DPDK-capable Ethernet controllers which makes mOS/mTCP compatible with certain 1/10 Gbps NICs (e.g. X540T1, I211 and many, many others). Ack to Juhyung. - Small coverity related fix. * tcp: handle ack with payload correctly in SYN_RECV state Signed-off-by: Jianbo Liu <jianbo.liu@linaro.org> * uses -m64 for x86_64 only to avoid compile error on other ARCHs Signed-off-by: Jianbo Liu <jianbo.liu@linaro.org> * add a generic ip_fast_csum for non-x86 platform Signed-off-by: Jianbo Liu <jianbo.liu@linaro.org> * - Stats bug that does not appear in kernel version <= 4.1.. but appears in linux-4.4. --> Always, always do copy_from_user() for user-space buffers before accessing them in kernel module. This one was hard to catch! --> Ack to Jaehyong for initially reporting the problem. * - Adding partial support for i40e. --> Still working on mtcp_init_rss() function for i40e. --> Server-side applications should work fine with mTCP. * - Removed redundant printk lines (in igbuio.c). - mtcp_init_rss() for i40e fixed. --> According to xl710 controller data sheet, the secret key should be 52 bytes long --> Intel 10 Gbps nic controllers previously relied on 40 bytes RSK --> See http://www.intel.co.kr/content/dam/www/public/us/en/documents/datasheets/xl710-10-40-controller-datasheet.pdf section 7.1.10.1 for details. - Made the code backward compatible with linux-3.x --> Previous code changes were made in linux-4.4.x - Added logic to unmap the pci address when driver (igb_uio) is deregistered. --> Now igb_uio-registered devices can be re-attached to i40e devices back and forth. * - Resovles issue# 67. * fix the bug in cofiguring mTCP when running ab (issue 124) ref:#124 * reset errno to 0 before calling strtol (resolves issue 128) ref:#128 * - Make sure that even non-TCP packets are uniformly distributed across cores. * Fix unused return value for copy_from_user(). (issue# 132) * add support for configuring discrete ports (resolves issue 125) ref:#125 * make backlog a command option (resolves the issue 136) ref:#136 * - Small update. * - Patch suggested by gchen-viosoft. * - Small patch to make it work for linux-4.2 * - Removed the MAX_CPUS restriction. - Make sure that hyperthreading is disabled before setting up mTCP - igb_uio driver will maintain netdev stats for up to 128 queues. * - Removed a statistics-related bug in epwget.c - Removed a race condition in cleaning up context resources during termination of application. * - Revised MAX_CPUs macro setup. * - Forgot to update README.md file. * - Small optimization related to CPU RSS calculation (rss-side) -> Thanks Ilwoo * - Small fixes (thanks to YoungGyoun Moon) * - Made it compatible with linux kernel versions >= 4.11.0 * - Updating travis configuration file slightly. * - Updating travis configuration file slightly. - Updating Id. * - Small typo in travis file. * - Small update to the tcp sent window logic * - Slight updates to the README/README.md files. * - Resolved issue #51 * Update from eunyoung14/mtcp (#3) * - IP defrag module for dpdk integrated (partly derived from ip_reassembly/ example code). -> Currently disabled... because I need some testing suite that can fragment IP datagrams - Cleaned up the Makefile.in scripts. * - Fixed an ICMP-related bug that was accidentally introduced when hw-chksumming was implemented. - Cleaned up the Makefile.in script - Cleaned up dpdk_module.c file. * - Applied fixes for suspect snippets identified by Coverity. - Added IP_DEFRAG warning. * - More fixes. * Adding coverity badge. - Needs more code fixing :S * - Minor fixes. * - Minor error checks. * - More & more fixes. * - Forgot to check in these files. * - More error checking. * - Added more DPDK-capable Ethernet controllers which makes mOS/mTCP compatible with certain 1/10 Gbps NICs (e.g. X540T1, I211 and many, many others). Ack to Juhyung. - Small coverity related fix. * tcp: handle ack with payload correctly in SYN_RECV state Signed-off-by: Jianbo Liu <jianbo.liu@linaro.org> * uses -m64 for x86_64 only to avoid compile error on other ARCHs Signed-off-by: Jianbo Liu <jianbo.liu@linaro.org> * add a generic ip_fast_csum for non-x86 platform Signed-off-by: Jianbo Liu <jianbo.liu@linaro.org> * - Stats bug that does not appear in kernel version <= 4.1.. but appears in linux-4.4. --> Always, always do copy_from_user() for user-space buffers before accessing them in kernel module. This one was hard to catch! --> Ack to Jaehyong for initially reporting the problem. * - Adding partial support for i40e. --> Still working on mtcp_init_rss() function for i40e. --> Server-side applications should work fine with mTCP. * - Removed redundant printk lines (in igbuio.c). - mtcp_init_rss() for i40e fixed. --> According to xl710 controller data sheet, the secret key should be 52 bytes long --> Intel 10 Gbps nic controllers previously relied on 40 bytes RSK --> See http://www.intel.co.kr/content/dam/www/public/us/en/documents/datasheets/xl710-10-40-controller-datasheet.pdf section 7.1.10.1 for details. - Made the code backward compatible with linux-3.x --> Previous code changes were made in linux-4.4.x - Added logic to unmap the pci address when driver (igb_uio) is deregistered. --> Now igb_uio-registered devices can be re-attached to i40e devices back and forth. * - Resovles issue# 67. * fix the bug in cofiguring mTCP when running ab (issue 124) ref:#124 * reset errno to 0 before calling strtol (resolves issue 128) ref:#128 * - Make sure that even non-TCP packets are uniformly distributed across cores. * Fix unused return value for copy_from_user(). (issue# 132) * add support for configuring discrete ports (resolves issue 125) ref:#125 * make backlog a command option (resolves the issue 136) ref:#136 * - Small update. * - Patch suggested by gchen-viosoft. * - Small patch to make it work for linux-4.2 * - Removed the MAX_CPUS restriction. - Make sure that hyperthreading is disabled before setting up mTCP - igb_uio driver will maintain netdev stats for up to 128 queues. * - Removed a statistics-related bug in epwget.c - Removed a race condition in cleaning up context resources during termination of application. * - Revised MAX_CPUs macro setup. * - Forgot to update README.md file. * - Small optimization related to CPU RSS calculation (rss-side) -> Thanks Ilwoo * - Small fixes (thanks to YoungGyoun Moon) * - Made it compatible with linux kernel versions >= 4.11.0 * - Updating travis configuration file slightly. * - Updating travis configuration file slightly. - Updating Id. * - Small typo in travis file. * - Small update to the tcp sent window logic * - Slight updates to the README/README.md files. * - Resolved issue #51 * onvm-mtcp cleaning * Added a build with onvm config option * Ifdefs for ONVM setup, ENABLE_ONVM flag * Update README.md for ONVM module * Aborting the old changes for a clean merge * README.md updates * README.md updates * Update epserver.conf onvm args explanation * Update epserver.conf * Added routing table rule for onvm-module * Update README * Update README.mdmaster
parent
5c8b4531ff
commit
3643bda209
|
@ -9,6 +9,7 @@ notifications:
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- env: COMPILER=gcc VERSION=6
|
||||
- env: COMPILER=gcc VERSION=5
|
||||
- env: COMPILER=gcc VERSION=4.8
|
||||
|
||||
|
@ -16,7 +17,9 @@ before_install:
|
|||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
- |
|
||||
if [ "$VERSION" = "5" ]; then
|
||||
if [ "$VERSION" = "6" ]; then
|
||||
sudo apt-get install -qq -y gcc-6
|
||||
elif [ "$VERSION" = "5" ]; then
|
||||
sudo apt-get install -qq -y gcc-5
|
||||
elif [ "$VERSION" = "4.8" ]; then
|
||||
sudo apt-get install -qq -y gcc-4.8
|
||||
|
@ -24,7 +27,9 @@ before_install:
|
|||
|
||||
before_script:
|
||||
- |
|
||||
if [ "$VERSION" = "5" ]; then
|
||||
if [ "$VERSION" = "6" ]; then
|
||||
export CC=gcc-6
|
||||
elif [ "$VERSION" = "5" ]; then
|
||||
export CC=gcc-5
|
||||
elif [ "$VERSION" = "4.8" ]; then
|
||||
export CC=gcc-4.8
|
||||
|
|
|
@ -231,6 +231,8 @@ MAKEINFO = @MAKEINFO@
|
|||
MKDIR_P = @MKDIR_P@
|
||||
NETMAP = @NETMAP@
|
||||
OBJEXT = @OBJEXT@
|
||||
ONVM = @ONVM@
|
||||
ONVMLIBPATH = @ONVMLIBPATH@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
|
|
79
README
79
README
|
@ -21,8 +21,11 @@ We require the following libraries to run mTCP.
|
|||
|
||||
|
||||
* We have modified the dpdk-16.11 package to export net_device stat data
|
||||
to the OS. To achieve this, the dpdk-16.11/lib/librte_eal/linuxapp/igb_uio/
|
||||
directory was updated. We recommend using our package for DPDK installation.
|
||||
(for Intel-based Ethernet adapters only) to the OS. To achieve this, the
|
||||
dpdk-16.11/lib/librte_eal/linuxapp/igb_uio/ directory was updated. We also
|
||||
modified mk/rte.app.mk and rte_cpuflags.mk files to ease the
|
||||
compilation process of mTCP applications. We recommend using our package
|
||||
for DPDK installation.
|
||||
|
||||
========================================================================
|
||||
INCLUDED DIRECTORIES
|
||||
|
@ -59,7 +62,7 @@ config - sample mTCP configuration files (may not be necessary)
|
|||
========================================================================
|
||||
INSTALL GUIDES
|
||||
========================================================================
|
||||
mTCP can be prepared in two ways.
|
||||
mTCP can be prepared in three ways.
|
||||
|
||||
- PSIO VERSION -
|
||||
----------------
|
||||
|
@ -78,6 +81,11 @@ mTCP can be prepared in two ways.
|
|||
# ./configure --with-psio-lib=<$path_to_ioengine>
|
||||
## e.g. ./configure --with-psio-lib=`echo $PWD`/io_engine
|
||||
# make
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 8-core system, by using the following command:
|
||||
# ./configure --with-psio-lib=`echo $PWD`/io_engine CFLAGS="-DMAX_CPUS=8"
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-3 (configure again):
|
||||
# autoreconf -ivf
|
||||
|
@ -96,13 +104,13 @@ mTCP can be prepared in two ways.
|
|||
- DPDK VERSION -
|
||||
----------------
|
||||
1. Set up Intel's DPDK driver. Please use our version of DPDK.
|
||||
We have only changed the lib/igb_uio/ submodule. The best
|
||||
method to compile DPDK package is to use DPDK's tools/setup.sh
|
||||
script. Please compile your package based on your own hardware
|
||||
configuration. We tested the mTCP stack on Intel Xeon E5-2690
|
||||
(x86_64) machine with Intel 82599 Ethernet adapters (10G). We
|
||||
used the following steps in the dpdk-setup.sh script for our
|
||||
setup:
|
||||
We have changed the lib/igb_uio/ submodule and a few makefiles
|
||||
in DPDK's mk/ subdirectory. The best method to compile DPDK
|
||||
package is to use DPDK's tools/setup.sh script. Please compile
|
||||
your package based on your own hardware configuration. We
|
||||
tested the mTCP stack on Intel Xeon E5-2690 (x86_64) machine
|
||||
with Intel 82599 Ethernet adapters (10G). We used the following
|
||||
steps in the dpdk-setup.sh script for our setup:
|
||||
|
||||
- Press [13] to compile the package
|
||||
- Press [16] to install the driver
|
||||
|
@ -118,6 +126,16 @@ mTCP can be prepared in two ways.
|
|||
on this page: http://dpdk.org/doc/nics. Please make sure that your
|
||||
NIC is compatible before moving on to the next step.
|
||||
|
||||
- recent Linux kernels tend to rename Ethernet interfaces based on
|
||||
their PCI addresses. If you are using Intel based Ethernet adapters,
|
||||
please rename the interface with a ``dpdk`` prefix. You can do so
|
||||
using the following command:
|
||||
|
||||
# sudo ifconfig <iface> down
|
||||
## where X is an integer value.
|
||||
## e.g. sudo ip link set ens786f0 name dpdk0
|
||||
# sudo ip link set <iface> name dpdkX
|
||||
|
||||
2. Next bring the dpdk-registered interfaces up. Please use the
|
||||
setup_iface_single_process.sh script file present in dpdk-16.11/tools/
|
||||
directory for this purpose. Please change lines 49-51 to change the IP
|
||||
|
@ -137,6 +155,11 @@ mTCP can be prepared in two ways.
|
|||
## And not dpdk-16.11!
|
||||
## e.g. ./configure --with-dpdk-lib=`echo $PWD`/dpdk
|
||||
# make
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 32-core system, by using the following command:
|
||||
# ./configure --with-dpdk-lib=$<path_to_mtcp_release_v3>/dpdk CFLAGS="-DMAX_CPUS=32"
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-4 (configure again):
|
||||
# autoreconf -ivf
|
||||
|
@ -156,6 +179,41 @@ mTCP can be prepared in two ways.
|
|||
|
||||
6. Run the applications!
|
||||
|
||||
- ONVM VERSION -
|
||||
----------------
|
||||
Install openNetVM following these instructions
|
||||
https://github.com/sdnfv/openNetVM/blob/master/docs/Install.md
|
||||
|
||||
1-3. ONVM uses DPDK so follow the dpdk installation up until step 4
|
||||
|
||||
4. Setup mtcp library
|
||||
# ./configure --with-dpdk-lib=$<path_to_dpdk> --with-onvm-lib=$<path_to_onvm_lib>
|
||||
# make
|
||||
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 32-core system, by using the following command:
|
||||
# ./configure --with-dpdk-lib=$<path_to_mtcp_release_v3>/dpdk --with-onvm-lib=$<path_to_onvm_lib> CFLAGS="-DMAX_CPUS=32"
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-4 (configure again):
|
||||
# autoreconf -ivf
|
||||
- checksum offloading in the NIC is now ENABLED (by default)!!!
|
||||
- this only works for dpdk at the moment
|
||||
- use
|
||||
./configure --with-dpdk-lib=`echo $PWD`/dpdk --disable-hwcsum
|
||||
to disable checksum offloading.
|
||||
- check libmtcp.a in mtcp/lib
|
||||
- check header files in mtcp/include
|
||||
- check example binary files in apps/example
|
||||
|
||||
5. Check the configurations in apps/example
|
||||
- epserver.conf for server-side configuration
|
||||
- epwget.conf for client-side configuration
|
||||
- you may write your own configuration file for your application
|
||||
|
||||
6. Run the applications!
|
||||
========================================================================
|
||||
TESTED ENVIRONMENTS
|
||||
========================================================================
|
||||
|
@ -203,6 +261,7 @@ We tested the DPDK version (polling driver) with Linux-3.13.0 kernel.
|
|||
1. Intel-82598 ixgbe (Max-queue-limit: 16)
|
||||
2. Intel-82599 ixgbe (Max-queue-limit: 16)
|
||||
3. Intel-I350 igb (Max-queue-limit: 08)
|
||||
4. Intel-X710 i40e (Max-queue-limit: ~)
|
||||
|
||||
========================================================================
|
||||
FREQUENTLY ASKED QUESTIONS
|
||||
|
|
113
README.md
113
README.md
|
@ -1,17 +1,8 @@
|
|||
[![Build Status](https://travis-ci.org/eunyoung14/mtcp.svg?branch=master)](https://travis-ci.org/eunyoung14/mtcp)
|
||||
[![Build Status](https://scan.coverity.com/projects/11896/badge.svg)](https://scan.coverity.com/projects/eunyoung14-mtcp)
|
||||
|
||||
# README #
|
||||
|
||||
### This application was modified to work with [ONVM][onvm] ###
|
||||
+ Currently only supports single core usage
|
||||
+ Tested with the provided application epserver
|
||||
|
||||
|
||||
#### INSTALL DIFFERENCES ####
|
||||
+ Follow the installation steps for dpdk version
|
||||
+ Make sure to set ONVM and RTE_SDK env path variable
|
||||
|
||||
|
||||
mTCP is a highly scalable user-level TCP stack for multicore systems.
|
||||
mTCP source code is distributed under the Modified BSD License. For
|
||||
more detail, please refer to the LICENSE. The license term of io_engine
|
||||
|
@ -24,12 +15,16 @@ We require the following libraries to run mTCP.
|
|||
- ``libnuma``
|
||||
- ``libpthread``
|
||||
- ``librt``
|
||||
Compling PSIO/DPDK driver requires kernel headers.
|
||||
|
||||
Compling PSIO/DPDK driver requires kernel headers.
|
||||
- For Debian/Ubuntu, try ``apt-get install linux-headers-$(uname -r)``
|
||||
|
||||
We have modified the dpdk-16.11 package to export net_device stat data
|
||||
to the OS. To achieve this, the dpdk-16.11/lib/librte_eal/linuxapp/igb_uio/
|
||||
directory was updated. We recommend using our package for DPDK installation.
|
||||
(for Intel-based Ethernet adapters only) to the OS. To achieve this, the
|
||||
dpdk-16.11/lib/librte_eal/linuxapp/igb_uio/ directory was updated. We also modified
|
||||
``mk/rte.app.mk`` and ``rte_cpuflags.mk`` files to ease the compilation
|
||||
process of mTCP applications. We recommend using our package for DPDK
|
||||
installation.
|
||||
|
||||
### INCLUDED DIRECTORIES ###
|
||||
|
||||
|
@ -64,7 +59,7 @@ config: sample mTCP configuration files (may not be necessary)
|
|||
|
||||
### INSTALL GUIDES ###
|
||||
|
||||
mTCP can be prepared in two ways.
|
||||
mTCP can be prepared in three ways.
|
||||
|
||||
***PSIO VERSION***
|
||||
|
||||
|
@ -88,6 +83,14 @@ mTCP can be prepared in two ways.
|
|||
## e.g. ./configure --with-psio-lib=`echo $PWD`/io_engine
|
||||
# make
|
||||
```
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 8-core system, by using the following command:
|
||||
```bash
|
||||
# ./configure --with-psio-lib=`echo $PWD`/io_engine CFLAGS="-DMAX_CPUS=8"
|
||||
```
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-3 (configure again):
|
||||
|
||||
|
@ -107,13 +110,13 @@ mTCP can be prepared in two ways.
|
|||
***DPDK VERSION***
|
||||
|
||||
1. Set up Intel's DPDK driver. Please use our version of DPDK.
|
||||
We have only changed the lib/igb_uio/ submodule. The best
|
||||
method to compile DPDK package is to use DPDK's tools/setup.sh
|
||||
script. Please compile your package based on your own hardware
|
||||
configuration. We tested the mTCP stack on Intel Xeon E5-2690
|
||||
(x86_64) machine with Intel 82599 Ethernet adapters (10G). We
|
||||
used the following steps in the dpdk-setup.sh script for our
|
||||
setup:
|
||||
We have changed the lib/igb_uio/ submodule and a few makefiles
|
||||
in DPDK's ``mk/`` subdirectory. The best method to compile DPDK
|
||||
package is to use DPDK's tools/setup.sh script. Please compile
|
||||
your package based on your own hardware configuration. We tested
|
||||
the mTCP stack on Intel Xeon E5-2690 (x86_64) machine with Intel
|
||||
82599 Ethernet adapters (10G). We used the following steps in
|
||||
the dpdk-setup.sh script for our setup:
|
||||
|
||||
- Press [13] to compile the package
|
||||
- Press [16] to install the driver
|
||||
|
@ -129,6 +132,18 @@ mTCP can be prepared in two ways.
|
|||
on this page: http://dpdk.org/doc/nics. Please make sure that your
|
||||
NIC is compatible before moving on to the next step.
|
||||
|
||||
- recent Linux kernels tend to rename Ethernet interfaces based on
|
||||
their PCI addresses. If you are using Intel based Ethernet adapters,
|
||||
please rename the interface with a ``dpdk`` prefix. You can do so
|
||||
using the following command:
|
||||
|
||||
```bash
|
||||
# sudo ifconfig <iface> down
|
||||
## where X is an integer value.
|
||||
## e.g. sudo ip link set ens786f0 name dpdk0
|
||||
# sudo ip link set <iface> name dpdkX
|
||||
```
|
||||
|
||||
2. Next bring the dpdk-registered interfaces up. Please use the
|
||||
``setup_iface_single_process.sh`` script file present in ``dpdk-16.11/tools/``
|
||||
directory for this purpose. Please change lines 49-51 to change the IP
|
||||
|
@ -152,6 +167,15 @@ mTCP can be prepared in two ways.
|
|||
## e.g. ./configure --with-dpdk-lib=`echo $PWD`/dpdk
|
||||
# make
|
||||
```
|
||||
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 32-core system, by using the following command:
|
||||
```bash
|
||||
# ./configure --with-dpdk-lib=$<path_to_mtcp_release_v3>/dpdk CFLAGS="-DMAX_CPUS=32"
|
||||
```
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-4 (configure again):
|
||||
|
||||
|
@ -170,6 +194,45 @@ mTCP can be prepared in two ways.
|
|||
|
||||
6. Run the applications!
|
||||
|
||||
|
||||
***ONVM VERSION***
|
||||
|
||||
[Install openNetVM following these instructions](https://github.com/sdnfv/openNetVM/blob/master/docs/Install.md)
|
||||
|
||||
*ONVM uses DPDK so follow the dpdk installation up until step 4*
|
||||
|
||||
4. Setup mtcp library
|
||||
```bash
|
||||
# ./configure --with-dpdk-lib=$<path_to_dpdk> --with-onvm-lib=$<path_to_onvm_lib>
|
||||
# make
|
||||
```
|
||||
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 32-core system, by using the following command:
|
||||
```bash
|
||||
# ./configure --with-dpdk-lib=$<path_to_mtcp_release_v3>/dpdk --with-onvm-lib=$<path_to_onvm_lib> CFLAGS="-DMAX_CPUS=32"
|
||||
```
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-4 (configure again):
|
||||
|
||||
```# autoreconf -ivf```
|
||||
- checksum offloading in the NIC is now ENABLED (by default)!!!
|
||||
- this only works for dpdk at the moment
|
||||
- use ```./configure --with-dpdk-lib=`echo $PWD`/dpdk --with-onvm-lib=$<path_to_onvm_lib> --disable-hwcsum``` to disable checksum offloading.
|
||||
- check libmtcp.a in mtcp/lib
|
||||
- check header files in mtcp/include
|
||||
- check example binary files in apps/example
|
||||
|
||||
5. Check the configurations in apps/example
|
||||
- epserver.conf for server-side configuration
|
||||
- epwget.conf for client-side configuration
|
||||
- you may write your own configuration file for your application
|
||||
|
||||
6. Run the applications!
|
||||
|
||||
***TESTED ENVIRONMENTS***
|
||||
|
||||
mTCP runs on Linux-based operating systems (2.6.x for PSIO) with generic
|
||||
|
@ -211,8 +274,9 @@ We tested the DPDK version (polling driver) with Linux-3.13.0 kernel.
|
|||
5. mTCP has been tested with the following Ethernet adapters:
|
||||
|
||||
1. Intel-82598 ixgbe (Max-queue-limit: 16)
|
||||
2. Intel-82599 ixgbe (Max-queue-limit: 16)
|
||||
3. Intel-I350 igb (Max-queue-limit: 08)
|
||||
2. Intel-82599 ixgbe (Max-queue-limit: 16)
|
||||
3. Intel-I350 igb (Max-queue-limit: 08)
|
||||
4. Intel-X710 i40e (Max-queue-limit: ~)
|
||||
|
||||
***FREQUENTLY ASKED QUESTIONS***
|
||||
|
||||
|
@ -243,6 +307,3 @@ We tested the DPDK version (polling driver) with Linux-3.13.0 kernel.
|
|||
April 2, 2015.
|
||||
EunYoung Jeong <notav at ndsl.kaist.edu>
|
||||
M. Asim Jamshed <ajamshed at ndsl.kaist.edu>
|
||||
|
||||
|
||||
[onvm]: http://sdnfv.github.io/onvm/
|
||||
|
|
|
@ -59,6 +59,11 @@
|
|||
2. Setup mtcp library:
|
||||
# ./configure --enable-netmap
|
||||
# make
|
||||
- By default, mTCP assumes that there are 16 CPUs in your system.
|
||||
You can set the CPU limit, e.g. on a 32-core system, by using the following command:
|
||||
# ./configure --enable-netmap CFLAGS="-DMAX_CPUS=32"
|
||||
Please note that your NIC should support RSS queues equal to the MAX_CPUS value
|
||||
(since mTCP expects a one-to-one RSS queue to CPU binding).
|
||||
- In case `./configure' script prints an error, run the
|
||||
following command; and then re-do step-2 (configure again):
|
||||
# autoreconf -ivf
|
||||
|
|
|
@ -2317,6 +2317,9 @@ static int open_postfile(const char *pfile)
|
|||
|
||||
int main(int argc, const char * const argv[])
|
||||
{
|
||||
#ifdef HAVE_MTCP
|
||||
struct mtcp_conf mcfg;
|
||||
#endif
|
||||
int r, l;
|
||||
char tmp[1024];
|
||||
apr_status_t status;
|
||||
|
@ -2386,6 +2389,11 @@ int main(int argc, const char * const argv[])
|
|||
break;
|
||||
case 'N':
|
||||
_num_cpus = atoi(optarg);
|
||||
#ifdef HAVE_MTCP
|
||||
mtcp_getconf(&mcfg);
|
||||
mcfg.num_cores = _num_cpus;
|
||||
mtcp_setconf(&mcfg);
|
||||
#endif
|
||||
break;
|
||||
case 'l':
|
||||
num_ports = atoi(optarg);
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
# TODO: Make this Makefile.in pretty
|
||||
|
||||
TARGETS = epserver epwget
|
||||
CC=@CC@ -g -O3 -Wall -Werror -fgnu89-inline
|
||||
DPDK=@DPDK@
|
||||
PS=@PSIO@
|
||||
NETMAP=@NETMAP@
|
||||
|
||||
### Check onvm related env vars ###
|
||||
ifeq ($(RTE_SDK),)
|
||||
$(error "Please define RTE_SDK environment variable")
|
||||
endif
|
||||
|
||||
ifeq ($(ONVM),)
|
||||
$(error "Please define ONVM environment variable")
|
||||
endif
|
||||
ONVM=@ONVM@
|
||||
CFLAGS=@CFLAGS@
|
||||
|
||||
# DPDK LIBRARY and HEADER
|
||||
DPDK_INC=@DPDKLIBPATH@/include
|
||||
|
@ -25,7 +20,7 @@ MTCP_TARGET = ${MTCP_LIB}/libmtcp.a
|
|||
|
||||
UTIL_FLD = ../../util
|
||||
UTIL_INC = -I${UTIL_FLD}/include
|
||||
UTIL_OBJ = ${UTIL_FLD}/http_parsing.o ${UTIL_FLD}/tdate_parse.o
|
||||
UTIL_OBJ = ${UTIL_FLD}/http_parsing.o ${UTIL_FLD}/tdate_parse.o ${UTIL_FLD}/netlib.o
|
||||
|
||||
|
||||
PS_DIR = ../../io_engine/
|
||||
|
@ -48,6 +43,29 @@ DPDK_MACHINE_FLAGS = $(shell cat @DPDKLIBPATH@/include/cflags.txt)
|
|||
INC += ${DPDK_MACHINE_FLAGS} -I${DPDK_INC} -include $(DPDK_INC)/rte_config.h
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -m),x86_64)
|
||||
LIBS += -m64
|
||||
endif
|
||||
|
||||
ifeq ($(DPDK),1)
|
||||
DPDK_LIB_FLAGS = $(shell cat @DPDKLIBPATH@/lib/ldflags.txt)
|
||||
#LIBS += -m64 -g -O3 -pthread -lrt -march=native -Wl,-export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -Wl,-lnuma -Wl,-lmtcp -Wl,-lpthread -Wl,-lrt -Wl,-ldl -Wl,${DPDK_LIB_FLAGS}
|
||||
LIBS += -g -O3 -pthread -lrt -march=native -export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -lnuma -lmtcp -lpthread -lrt -ldl ${DPDK_LIB_FLAGS}
|
||||
else
|
||||
#LIBS += -m64 -g -O3 -pthread -lrt -march=native -Wl,-export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -Wl,-lnuma -Wl,-lmtcp -Wl,-lpthread -Wl,-lrt -Wl,-ldl -Wl,${DPDK_LIB_FLAGS}
|
||||
LIBS += -g -O3 -pthread -lrt -march=native -export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -lnuma -lmtcp -lpthread -lrt -ldl ${DPDK_LIB_FLAGS}
|
||||
endif
|
||||
|
||||
ifeq ($(ONVM),1)
|
||||
ifeq ($(RTE_TARGET),)
|
||||
$(error "Please define RTE_TARGET environment variable")
|
||||
endif
|
||||
|
||||
INC += -I@ONVMLIBPATH@/onvm_nflib
|
||||
INC += -DENABLE_ONVM
|
||||
LIBS += @ONVMLIBPATH@/onvm_nflib/onvm_nflib/$(RTE_TARGET)/libonvm.a
|
||||
endif
|
||||
|
||||
ifeq ($V,) # no echo
|
||||
export MSG=@echo
|
||||
export HIDE=@
|
||||
|
@ -56,25 +74,13 @@ else
|
|||
export HIDE=
|
||||
endif
|
||||
|
||||
ifeq ($(DPDK),1)
|
||||
DPDK_LIB_FLAGS = $(shell cat @DPDKLIBPATH@/lib/ldflags.txt)
|
||||
#LIBS += -m64 -g -O3 -pthread -lrt -march=native -Wl,-export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -Wl,-lnuma -Wl,-lmtcp -Wl,-lpthread -Wl,-lrt -Wl,-ldl -Wl,${DPDK_LIB_FLAGS}
|
||||
LIBS += -m64 -g -O3 -pthread -lrt -march=native -export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -lnuma -lmtcp -lpthread -lrt -ldl ${DPDK_LIB_FLAGS}
|
||||
else
|
||||
#LIBS += -m64 -g -O3 -pthread -lrt -march=native -Wl,-export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -Wl,-lnuma -Wl,-lmtcp -Wl,-lpthread -Wl,-lrt -Wl,-ldl -Wl,${DPDK_LIB_FLAGS}
|
||||
LIBS += -m64 -g -O3 -pthread -lrt -march=native -export-dynamic ${MTCP_FLD}/lib/libmtcp.a -L../../dpdk/lib -lnuma -lmtcp -lpthread -lrt -ldl ${DPDK_LIB_FLAGS}
|
||||
endif
|
||||
|
||||
INC += -I$(ONVM)/onvm_nflib
|
||||
LIBS += $(ONVM)/onvm_nflib/onvm_nflib/$(RTE_TARGET)/libonvm.a
|
||||
|
||||
all: epserver epwget
|
||||
|
||||
epserver.o: epserver.c
|
||||
$(MSG) " CC $<"
|
||||
$(HIDE) ${CC} -c $< ${CFLAGS} ${INC}
|
||||
|
||||
epserver: epserver.o
|
||||
epserver: epserver.o ${MTCP_FLD}/lib/libmtcp.a
|
||||
$(MSG) " LD $<"
|
||||
$(HIDE) ${CC} $< ${LIBS} ${UTIL_OBJ} -o $@
|
||||
|
||||
|
@ -82,7 +88,7 @@ epwget.o: epwget.c
|
|||
$(MSG) " CC $<"
|
||||
$(HIDE) ${CC} -c $< ${CFLAGS} ${INC}
|
||||
|
||||
epwget: epwget.o
|
||||
epwget: epwget.o ${MTCP_FLD}/lib/libmtcp.a
|
||||
$(MSG) " LD $<"
|
||||
$(HIDE) ${CC} $< ${LIBS} ${UTIL_OBJ} -o $@
|
||||
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
This example application was modified to work with onvm
|
||||
|
||||
========================================================================
|
||||
USAGE OF EXAMPLE APPLICATIONS
|
||||
========================================================================
|
||||
|
||||
epserver: a simple mtcp-epoll-based web server
|
||||
Single-Process, Multi-threaded Usage:
|
||||
./epserver -p www_home -f epserver.conf [-N #cores] [-c core_list] -- [-s service_id]
|
||||
ex) ./epserver -p /home/notav/www -f epserver.conf -N 1 -c 6 -- -r 1
|
||||
./epserver -p www_home -f epserver.conf [-N #cores]
|
||||
ex) ./epserver -p /home/notav/www -f epserver.conf -N 8
|
||||
|
||||
Multi-Process, Single-threaded Usage [DPDK-only]
|
||||
(Master runs on core 0 by default, Slave processes on core 1~N)
|
||||
ex) ./epserver -p /home/notav/www -f epserver-master.conf -c 0
|
||||
for i in {1..7}
|
||||
do
|
||||
./epserver -p /home/notav/www -f epserver-slave.conf -c $i
|
||||
done
|
||||
|
||||
|
||||
options:
|
||||
|
@ -16,15 +22,8 @@ options:
|
|||
-N: number of CPU cores to use. default: all existing cores
|
||||
-p: path to www/ files
|
||||
-f: path to mtcp configuration file
|
||||
-c: the core_list on which the process should run
|
||||
[So far only single core is supported]
|
||||
onvm args after --
|
||||
-n: instanse id
|
||||
-r: service id
|
||||
-d: destination id
|
||||
|
||||
Epserver doesn't support large files
|
||||
- Large files roughly > 10 Megabytes are currently causing an error in rte_eal_init for dpdk/onvm setup
|
||||
-c: the core_id on which the process should run
|
||||
[only works for multi-process mode]
|
||||
|
||||
========================================================================
|
||||
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <mtcp_api.h>
|
||||
#include <mtcp_epoll.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "http_parsing.h"
|
||||
#include "netlib.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define MAX_FLOW_NUM (10000)
|
||||
|
@ -32,11 +34,10 @@
|
|||
#define HTTP_HEADER_LEN 1024
|
||||
#define URL_LEN 128
|
||||
|
||||
#define MAX_CPUS 16
|
||||
#define MAX_FILES 30
|
||||
|
||||
#define MAX(a, b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a, b) ((a)<(b)?(a):(b))
|
||||
#define NAME_LIMIT 128
|
||||
#define FULLNAME_LIMIT 256
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
|
@ -52,11 +53,14 @@
|
|||
|
||||
#define HT_SUPPORT FALSE
|
||||
|
||||
#ifndef MAX_CPUS
|
||||
#define MAX_CPUS 16
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
struct file_cache
|
||||
{
|
||||
char name[128];
|
||||
char fullname[256];
|
||||
char name[NAME_LIMIT];
|
||||
char fullname[FULLNAME_LIMIT];
|
||||
uint64_t size;
|
||||
char *file;
|
||||
};
|
||||
|
@ -72,7 +76,7 @@ struct server_vars
|
|||
uint8_t keep_alive;
|
||||
|
||||
int fidx; // file cache index
|
||||
char fname[128]; // file name
|
||||
char fname[NAME_LIMIT]; // file name
|
||||
long int fsize; // file size
|
||||
};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -88,6 +92,7 @@ static int core_limit;
|
|||
static pthread_t app_thread[MAX_CPUS];
|
||||
static int done[MAX_CPUS];
|
||||
static char *conf_file = NULL;
|
||||
static int backlog = -1;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
const char *www_main;
|
||||
static struct file_cache fcache[MAX_FILES];
|
||||
|
@ -332,12 +337,15 @@ InitializeServerThread(int core)
|
|||
ctx->mctx = mtcp_create_context(core);
|
||||
if (!ctx->mctx) {
|
||||
TRACE_ERROR("Failed to create mtcp context!\n");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create epoll descriptor */
|
||||
ctx->ep = mtcp_epoll_create(ctx->mctx, MAX_EVENTS);
|
||||
if (ctx->ep < 0) {
|
||||
mtcp_destroy_context(ctx->mctx);
|
||||
free(ctx);
|
||||
TRACE_ERROR("Failed to create epoll descriptor!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -346,6 +354,9 @@ InitializeServerThread(int core)
|
|||
ctx->svars = (struct server_vars *)
|
||||
calloc(MAX_FLOW_NUM, sizeof(struct server_vars));
|
||||
if (!ctx->svars) {
|
||||
mtcp_close(ctx->mctx, ctx->ep);
|
||||
mtcp_destroy_context(ctx->mctx);
|
||||
free(ctx);
|
||||
TRACE_ERROR("Failed to create server_vars struct!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -384,8 +395,8 @@ CreateListeningSocket(struct thread_context *ctx)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* listen (backlog: 4K) */
|
||||
ret = mtcp_listen(ctx->mctx, listener, 4096);
|
||||
/* listen (backlog: can be configured) */
|
||||
ret = mtcp_listen(ctx->mctx, listener, backlog);
|
||||
if (ret < 0) {
|
||||
TRACE_ERROR("mtcp_listen() failed!\n");
|
||||
return -1;
|
||||
|
@ -537,15 +548,13 @@ static void
|
|||
printHelp(const char *prog_name)
|
||||
{
|
||||
TRACE_CONFIG("%s -p <path_to_www/> -f <mtcp_conf_file> "
|
||||
"[-N num_cores] [-c <core_list>] [-h] "
|
||||
"-- [-n onvm_instance_id] [-r onvm_service_id] "
|
||||
"[-d onvm_dest_id]\n",
|
||||
"[-N num_cores] [-c <per-process core_id>] [-h]\n",
|
||||
prog_name);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
@ -553,26 +562,21 @@ main(int argc, char *argv[])
|
|||
int ret;
|
||||
uint64_t total_read;
|
||||
struct mtcp_conf mcfg;
|
||||
int core_list[MAX_CPUS];
|
||||
int cores[MAX_CPUS];
|
||||
int process_cpu;
|
||||
int o;
|
||||
int i, val;
|
||||
char *core_list_tokens;
|
||||
|
||||
int i, o;
|
||||
|
||||
num_cores = GetNumCPUs();
|
||||
core_limit = num_cores;
|
||||
process_cpu = -1;
|
||||
dir = NULL;
|
||||
i = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
TRACE_CONFIG("$%s directory_to_service\n", argv[0]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mtcp_getconf(&mcfg);
|
||||
|
||||
while (-1 != (o = getopt(argc, argv, "N:f:p:c:h"))) {
|
||||
while (-1 != (o = getopt(argc, argv, "N:f:p:c:b:h"))) {
|
||||
switch (o) {
|
||||
case 'p':
|
||||
/* open the directory to serve */
|
||||
|
@ -585,59 +589,40 @@ main(int argc, char *argv[])
|
|||
}
|
||||
break;
|
||||
case 'N':
|
||||
core_limit = atoi(optarg);
|
||||
core_limit = mystrtol(optarg, 10);
|
||||
if (core_limit > num_cores) {
|
||||
TRACE_CONFIG("CPU limit should be smaller than the "
|
||||
"number of CPUs: %d\n", num_cores);
|
||||
return FALSE;
|
||||
}
|
||||
if (core_limit != 1) {
|
||||
TRACE_CONFIG("Multi core is currently NOT supported, "
|
||||
"use -N 1\n");
|
||||
return FALSE;
|
||||
}
|
||||
/**
|
||||
* it is important that core limit is set
|
||||
* before mtcp_init() is called. You can
|
||||
* not set core_limit after mtcp_init()
|
||||
*/
|
||||
mtcp_getconf(&mcfg);
|
||||
mcfg.num_cores = core_limit;
|
||||
mtcp_setconf(&mcfg);
|
||||
break;
|
||||
case 'f':
|
||||
conf_file = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
mcfg.core_list = optarg;
|
||||
process_cpu = mystrtol(optarg, 10);
|
||||
if (process_cpu > core_limit) {
|
||||
TRACE_CONFIG("Starting CPU is way off limits!\n");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
backlog = mystrtol(optarg, 10);
|
||||
break;
|
||||
case 'h':
|
||||
printHelp(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mtcp_setconf(&mcfg);
|
||||
|
||||
/* Modify argc/argv to correctly pass arguments to mtcp_parse_args */
|
||||
argv += optind-1;
|
||||
argc -= optind-1;
|
||||
|
||||
/* Check core_list was passed */
|
||||
if (mcfg.core_list == NULL){
|
||||
TRACE_CONFIG("You did not pass a valid core_list!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
core_list_tokens = malloc(sizeof(char) * strlen(mcfg.core_list));
|
||||
strcpy(core_list_tokens, mcfg.core_list);
|
||||
if (core_list_tokens == NULL){
|
||||
perror("core_list_tokens malloc");
|
||||
}
|
||||
}
|
||||
|
||||
while (core_list_tokens !=NULL){
|
||||
val = atoi(core_list_tokens);
|
||||
core_list[i++]=val;
|
||||
core_list_tokens = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
if (dir == NULL) {
|
||||
TRACE_CONFIG("You did not pass a valid www_path!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -650,8 +635,9 @@ main(int argc, char *argv[])
|
|||
else if (strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
strcpy(fcache[nfiles].name, ent->d_name);
|
||||
sprintf(fcache[nfiles].fullname, "%s/%s", www_main, ent->d_name);
|
||||
snprintf(fcache[nfiles].name, NAME_LIMIT, "%s", ent->d_name);
|
||||
snprintf(fcache[nfiles].fullname, FULLNAME_LIMIT, "%s/%s",
|
||||
www_main, ent->d_name);
|
||||
fd = open(fcache[nfiles].fullname, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
|
@ -701,22 +687,34 @@ main(int argc, char *argv[])
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = mtcp_init(conf_file, argc, argv);
|
||||
ret = mtcp_init(conf_file);
|
||||
if (ret) {
|
||||
TRACE_CONFIG("Failed to initialize mtcp\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mtcp_getconf(&mcfg);
|
||||
if (backlog > mcfg.max_concurrency) {
|
||||
TRACE_CONFIG("backlog can not be set larger than CONFIG.max_concurrency\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* if backlog is not specified, set it to 4K */
|
||||
if (backlog == -1) {
|
||||
backlog = 4096;
|
||||
}
|
||||
|
||||
/* register signal handler to mtcp */
|
||||
mtcp_register_signal(SIGINT, SignalHandler);
|
||||
|
||||
TRACE_INFO("Application initialization finished.\n");
|
||||
|
||||
for (i = 0; i < core_limit; i++) {
|
||||
done[core_list[i]] = FALSE;
|
||||
|
||||
for (i = ((process_cpu == -1) ? 0 : process_cpu); i < core_limit; i++) {
|
||||
cores[i] = i;
|
||||
done[i] = FALSE;
|
||||
|
||||
if (pthread_create(&app_thread[core_list[i]],
|
||||
NULL, RunServerThread, (void *)&core_list[i])) {
|
||||
if (pthread_create(&app_thread[i],
|
||||
NULL, RunServerThread, (void *)&cores[i])) {
|
||||
perror("pthread_create");
|
||||
TRACE_CONFIG("Failed to create server thread.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -725,8 +723,8 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < core_limit; i++) {
|
||||
pthread_join(app_thread[core_list[i]], NULL);
|
||||
for (i = ((process_cpu == -1) ? 0 : process_cpu); i < core_limit; i++) {
|
||||
pthread_join(app_thread[i], NULL);
|
||||
|
||||
if (process_cpu != -1)
|
||||
break;
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
# enable only one out of the two.
|
||||
#io = psio
|
||||
#io = netmap
|
||||
io = onvm
|
||||
#io = onvm
|
||||
io = dpdk
|
||||
|
||||
# No. of cores setting (enabling this option will override
|
||||
# the `cpu' config for those applications that accept
|
||||
|
@ -16,7 +17,17 @@ io = onvm
|
|||
#num_cores = 8
|
||||
|
||||
# Number of memory channels per processor socket (dpdk-only)
|
||||
num_mem_ch = 3
|
||||
num_mem_ch = 4
|
||||
|
||||
# ONVM specific args
|
||||
# Service id (required)
|
||||
#onvm_serv = 1
|
||||
#
|
||||
# Instance id (optional)
|
||||
#onvm_inst = 1
|
||||
# Destination id (will forward to another NF)
|
||||
# If not set will send packets out
|
||||
#onvm_dest = 2
|
||||
|
||||
# Enable multi-process support (under development)
|
||||
#multiprocess = 0 master
|
||||
|
@ -27,11 +38,10 @@ num_mem_ch = 3
|
|||
#port = xge0 xge1
|
||||
#port = xge1
|
||||
#------ DPDK ports -------#
|
||||
#port = dpdk1
|
||||
port = dpdk0
|
||||
#port = dpdk0 dpdk1
|
||||
#port = dpdk0:0
|
||||
#port = dpdk0:1
|
||||
port = dpdk0 dpdk1
|
||||
|
||||
# Maximum concurrency per core
|
||||
max_concurrency = 10000
|
||||
|
@ -41,7 +51,7 @@ max_concurrency = 10000
|
|||
max_num_buffers = 10000
|
||||
|
||||
# Receive buffer size of sockets
|
||||
rcvbuf = 8192
|
||||
rcvbuf = 8192
|
||||
|
||||
# Send buffer size of sockets
|
||||
sndbuf = 8192
|
||||
|
@ -59,9 +69,9 @@ tcp_timewait = 0
|
|||
#stat_print = xge0
|
||||
#stat_print = xge1
|
||||
#------ DPDK ports -------#
|
||||
stat_print = dpdk0
|
||||
#stat_print = dpdk0:0
|
||||
#stat_print = dpdk0:1
|
||||
#stat_print = dpdk1
|
||||
stat_print = dpdk0 dpdk1
|
||||
|
||||
#######################################################
|
||||
|
|
|
@ -15,16 +15,16 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <sys/queue.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <mtcp_api.h>
|
||||
#include <mtcp_epoll.h>
|
||||
#include "cpu.h"
|
||||
#include "rss.h"
|
||||
#include "http_parsing.h"
|
||||
#include "netlib.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define MAX_CPUS 16
|
||||
|
||||
#define MAX_URL_LEN 128
|
||||
#define MAX_FILE_LEN 128
|
||||
#define HTTP_HEADER_LEN 1024
|
||||
|
@ -40,9 +40,6 @@
|
|||
#define TIMEVAL_TO_USEC(t) ((t.tv_sec * 1000000) + (t.tv_usec))
|
||||
#define TS_GT(a,b) ((int64_t)((a)-(b)) > 0)
|
||||
|
||||
#define MAX(a, b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a, b) ((a)<(b)?(a):(b))
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
@ -55,6 +52,9 @@
|
|||
#define ERROR (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MAX_CPUS
|
||||
#define MAX_CPUS 16
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static pthread_t app_thread[MAX_CPUS];
|
||||
static mctx_t g_mctx[MAX_CPUS];
|
||||
|
@ -66,8 +66,8 @@ static int core_limit;
|
|||
static int fio = FALSE;
|
||||
static char outfile[MAX_FILE_LEN + 1];
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static char host[MAX_IP_STR_LEN + 1];
|
||||
static char url[MAX_URL_LEN + 1];
|
||||
static char host[MAX_IP_STR_LEN + 1] = {'\0'};
|
||||
static char url[MAX_URL_LEN + 1] = {'\0'};
|
||||
static in_addr_t daddr;
|
||||
static in_port_t dport;
|
||||
static in_addr_t saddr;
|
||||
|
@ -132,8 +132,8 @@ struct wget_vars
|
|||
int fd;
|
||||
};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static struct thread_context *g_ctx[MAX_CPUS];
|
||||
static struct wget_stat *g_stat[MAX_CPUS];
|
||||
static struct thread_context *g_ctx[MAX_CPUS] = {0};
|
||||
static struct wget_stat *g_stat[MAX_CPUS] = {0};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
thread_context_t
|
||||
CreateContext(int core)
|
||||
|
@ -151,6 +151,7 @@ CreateContext(int core)
|
|||
ctx->mctx = mtcp_create_context(core);
|
||||
if (!ctx->mctx) {
|
||||
TRACE_ERROR("Failed to create mtcp context.\n");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
g_mctx[core] = ctx->mctx;
|
||||
|
@ -161,6 +162,7 @@ CreateContext(int core)
|
|||
void
|
||||
DestroyContext(thread_context_t ctx)
|
||||
{
|
||||
g_stat[ctx->core] = NULL;
|
||||
mtcp_destroy_context(ctx->mctx);
|
||||
free(ctx);
|
||||
}
|
||||
|
@ -346,15 +348,23 @@ HandleReadEvent(thread_context_t ctx, int sockid, struct wget_vars *wv)
|
|||
wv->response[wv->header_len] = '\0';
|
||||
wv->file_len = http_header_long_val(wv->response,
|
||||
CONTENT_LENGTH_HDR, sizeof(CONTENT_LENGTH_HDR) - 1);
|
||||
if (wv->file_len < 0) {
|
||||
/* failed to find the Content-Length field */
|
||||
wv->recv += rd;
|
||||
rd = 0;
|
||||
CloseConnection(ctx, sockid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE_APP("Socket %d Parsed response header. "
|
||||
"Header length: %u, File length: %lu (%luMB)\n",
|
||||
sockid, wv->header_len,
|
||||
wv->file_len, wv->file_len / 1024 / 1024);
|
||||
wv->headerset = TRUE;
|
||||
wv->recv += (rd - (wv->resp_len - wv->header_len));
|
||||
rd = (wv->resp_len - wv->header_len);
|
||||
|
||||
pbuf += (rd - (wv->resp_len - wv->header_len));
|
||||
rd = (wv->resp_len - wv->header_len);
|
||||
//printf("Successfully parse header.\n");
|
||||
//fflush(stdout);
|
||||
|
||||
|
@ -476,6 +486,8 @@ PrintStats()
|
|||
|
||||
for (i = 0; i < core_limit; i++) {
|
||||
st = g_stat[i];
|
||||
|
||||
if (st == NULL) continue;
|
||||
avg_resp_time = st->completes? st->sum_resp_time / st->completes : 0;
|
||||
#if 0
|
||||
fprintf(stderr, "[CPU%2d] epoll_wait: %5lu, event: %7lu, "
|
||||
|
@ -500,7 +512,7 @@ PrintStats()
|
|||
total.errors += st->errors;
|
||||
total.timedout += st->timedout;
|
||||
|
||||
memset(st, 0, sizeof(struct wget_stat));
|
||||
memset(st, 0, sizeof(struct wget_stat));
|
||||
}
|
||||
fprintf(stderr, "[ ALL ] connect: %7lu, read: %4lu MB, write: %4lu MB, "
|
||||
"completes: %7lu (resp_time avg: %4lu, max: %6lu us)\n",
|
||||
|
@ -596,7 +608,7 @@ RunWgetMain(void *arg)
|
|||
|
||||
/* print statistics every second */
|
||||
if (core == 0 && cur_tv.tv_sec > prev_tv.tv_sec) {
|
||||
PrintStats();
|
||||
PrintStats();
|
||||
prev_tv = cur_tv;
|
||||
}
|
||||
|
||||
|
@ -711,14 +723,14 @@ main(int argc, char **argv)
|
|||
strncpy(url, strchr(argv[1], '/'), MAX_URL_LEN);
|
||||
} else {
|
||||
strncpy(host, argv[1], MAX_IP_STR_LEN);
|
||||
strncpy(url, "/", 1);
|
||||
strncpy(url, "/", 2);
|
||||
}
|
||||
|
||||
daddr = inet_addr(host);
|
||||
dport = htons(80);
|
||||
saddr = INADDR_ANY;
|
||||
|
||||
total_flows = atoi(argv[2]);
|
||||
total_flows = mystrtol(argv[2], 10);
|
||||
if (total_flows <= 0) {
|
||||
TRACE_CONFIG("Number of flows should be large than 0.\n");
|
||||
return FALSE;
|
||||
|
@ -729,11 +741,14 @@ main(int argc, char **argv)
|
|||
concurrency = 100;
|
||||
for (i = 3; i < argc - 1; i++) {
|
||||
if (strcmp(argv[i], "-N") == 0) {
|
||||
core_limit = atoi(argv[i + 1]);
|
||||
core_limit = mystrtol(argv[i + 1], 10);
|
||||
if (core_limit > num_cores) {
|
||||
TRACE_CONFIG("CPU limit should be smaller than the "
|
||||
"number of CPUS: %d\n", num_cores);
|
||||
return FALSE;
|
||||
} else if (core_limit < 1) {
|
||||
TRACE_CONFIG("CPU limit should be greater than 0\n");
|
||||
return FALSE;
|
||||
}
|
||||
/**
|
||||
* it is important that core limit is set
|
||||
|
@ -744,7 +759,7 @@ main(int argc, char **argv)
|
|||
mcfg.num_cores = core_limit;
|
||||
mtcp_setconf(&mcfg);
|
||||
} else if (strcmp(argv[i], "-c") == 0) {
|
||||
total_concurrency = atoi(argv[i + 1]);
|
||||
total_concurrency = mystrtol(argv[i + 1], 10);
|
||||
|
||||
} else if (strcmp(argv[i], "-o") == 0) {
|
||||
if (strlen(argv[i + 1]) > MAX_FILE_LEN) {
|
||||
|
|
|
@ -664,10 +664,12 @@ am__isrc
|
|||
INSTALL_DATA
|
||||
INSTALL_SCRIPT
|
||||
INSTALL_PROGRAM
|
||||
ONVMLIBPATH
|
||||
PSLIBPATH
|
||||
DPDKLIBPATH
|
||||
HWCSUM
|
||||
NETMAP
|
||||
ONVM
|
||||
PSIO
|
||||
LRO
|
||||
DPDK
|
||||
|
@ -1369,6 +1371,7 @@ Optional Packages:
|
|||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||
--with-dpdk-lib path to the dpdk-16.11 install root
|
||||
--with-psio-lib path to the ioengine install root
|
||||
--with-onvm-lib path to the onvm install root
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
|
@ -4102,6 +4105,9 @@ LRO=0
|
|||
# Reset PSIO to 0
|
||||
PSIO=0
|
||||
|
||||
# Reset ONVM to 0
|
||||
ONVM=0
|
||||
|
||||
# Reset NETMAP to 0
|
||||
NETMAP=0
|
||||
|
||||
|
@ -4178,6 +4184,21 @@ if test "x$enable_netmap" = "xyes"; then :
|
|||
|
||||
fi
|
||||
|
||||
# Check onvm lib path
|
||||
|
||||
# Check whether --with-stuff was given.
|
||||
if test "${with_stuff+set}" = set; then :
|
||||
withval=$with_stuff;
|
||||
fi
|
||||
|
||||
if test "$with_onvm_lib" != ""
|
||||
then
|
||||
ONVMLIBPATH=$with_onvm_lib
|
||||
|
||||
ONVM=1
|
||||
|
||||
fi
|
||||
|
||||
if test "$with_psio_lib" == "" && test "$with_dpdk_lib" == "" && test "x$enable_netmap" = "xno"
|
||||
then
|
||||
as_fn_error $? "Packet I/O library is missing. Please set either dpdk or psio or netmap as your I/O lib." "$LINENO" 5
|
||||
|
|
10
configure.ac
10
configure.ac
|
@ -47,6 +47,8 @@ AC_SUBST(DPDK, 0)
|
|||
AC_SUBST(LRO, 0)
|
||||
# Reset PSIO to 0
|
||||
AC_SUBST(PSIO, 0)
|
||||
# Reset ONVM to 0
|
||||
AC_SUBST(ONVM, 0)
|
||||
# Reset NETMAP to 0
|
||||
AC_SUBST(NETMAP, 0)
|
||||
# Reset HWCSUM to 1
|
||||
|
@ -96,6 +98,14 @@ AS_IF([test "x$enable_netmap" = "xyes"], [
|
|||
AC_SUBST(NETMAP, 1)
|
||||
])
|
||||
|
||||
# Check onvm lib path
|
||||
AC_ARG_WITH(stuff, [ --with-onvm-lib path to the onvm install root])
|
||||
if test "$with_onvm_lib" != ""
|
||||
then
|
||||
AC_SUBST(ONVMLIBPATH, $with_onvm_lib)
|
||||
AC_SUBST(ONVM, 1)
|
||||
fi
|
||||
|
||||
if test "$with_psio_lib" == "" && test "$with_dpdk_lib" == "" && test "x$enable_netmap" = "xno"
|
||||
then
|
||||
AC_MSG_ERROR([Packet I/O library is missing. Please set either dpdk or psio or netmap as your I/O lib.])
|
||||
|
|
|
@ -37,17 +37,43 @@ include $(RTE_SDK)/mk/rte.vars.mk
|
|||
MODULE = igb_uio
|
||||
MODULE_PATH = drivers/net/igb_uio
|
||||
|
||||
include $(RTE_SDK)/lib/librte_eal/linuxapp/igb_uio/i40e/common.mk
|
||||
|
||||
#
|
||||
# CFLAGS
|
||||
#
|
||||
MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=100
|
||||
MODULE_CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/i40e
|
||||
MODULE_CFLAGS += -I$(RTE_OUTPUT)/include
|
||||
MODULE_CFLAGS += -Winline -Wall -Werror
|
||||
MODULE_CFLAGS += -Wall -Werror
|
||||
MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
|
||||
|
||||
ifeq ($(shell lsb_release -si 2>/dev/null),Ubuntu)
|
||||
MODULE_CFLAGS += -DUBUNTU_RELEASE_CODE=$(shell lsb_release -sr | tr -d .)
|
||||
UBUNTU_KERNEL_CODE := $(shell echo `grep UTS_RELEASE $(RTE_KERNELDIR)/include/generated/utsrelease.h \
|
||||
| cut -d '"' -f2 | cut -d- -f1,2 | tr .- ,`,1)
|
||||
MODULE_CFLAGS += -D"UBUNTU_KERNEL_CODE=UBUNTU_KERNEL_VERSION($(UBUNTU_KERNEL_CODE))"
|
||||
endif
|
||||
|
||||
#
|
||||
# all source are stored in SRCS-y
|
||||
#
|
||||
SRCS-y := igb_uio.c
|
||||
SRCS-y := igbuio.c
|
||||
SRCS-y += i40e/i40e_main.c
|
||||
SRCS-y += i40e/i40e_adminq.c
|
||||
SRCS-y += i40e/i40e_dcb.c
|
||||
SRCS-y += i40e/i40e_diag.c
|
||||
SRCS-y += i40e/i40e_hmc.c
|
||||
SRCS-y += i40e/i40e_nvm.c
|
||||
SRCS-y += i40e/i40e_virtchnl_pf.c
|
||||
SRCS-y += i40e/i40e_client.c
|
||||
SRCS-y += i40e/i40e_dcb_nl.c
|
||||
SRCS-y += i40e/i40e_ethtool.c
|
||||
SRCS-y += i40e/i40e_lan_hmc.c
|
||||
SRCS-y += i40e/i40e_ptp.c
|
||||
SRCS-y += i40e/kcompat.c
|
||||
SRCS-y += i40e/i40e_common.c
|
||||
SRCS-y += i40e/i40e_debugfs.c
|
||||
SRCS-y += i40e/i40e_fcoe.c
|
||||
SRCS-y += i40e/i40e_txrx.c
|
||||
|
||||
include $(RTE_SDK)/mk/rte.module.mk
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
################################################################################
|
||||
#
|
||||
# Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
# Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# The full GNU General Public License is included in this distribution in
|
||||
# the file called "COPYING".
|
||||
#
|
||||
# Contact Information:
|
||||
# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
#
|
||||
################################################################################
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# kbuild part of makefile
|
||||
#
|
||||
# Makefile for the Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_I40E) += i40e.o
|
||||
|
||||
i40e-y := i40e_main.o \
|
||||
i40e_ethtool.o \
|
||||
i40e_adminq.o \
|
||||
i40e_common.o \
|
||||
i40e_hmc.o \
|
||||
i40e_lan_hmc.o \
|
||||
i40e_nvm.o \
|
||||
i40e_debugfs.o \
|
||||
i40e_diag.o \
|
||||
i40e_txrx.o \
|
||||
i40e_ptp.o \
|
||||
i40e_client.o \
|
||||
i40e_virtchnl_pf.o
|
||||
|
||||
i40e-$(CONFIG_DCB) += i40e_dcb.o i40e_dcb_nl.o
|
||||
i40e-$(CONFIG_FCOE:m=y) += i40e_fcoe.o
|
||||
i40e-y += kcompat.o
|
||||
|
||||
else # ifneq($(KERNELRELEASE),)
|
||||
# normal makefile
|
||||
|
||||
DRIVER := i40e
|
||||
|
||||
ifeq (,$(wildcard common.mk))
|
||||
$(error Cannot find common.mk build rules)
|
||||
else
|
||||
include common.mk
|
||||
endif
|
||||
|
||||
# i40e does not support building on kernels older than 2.6.32
|
||||
$(call minimum_kver_check,2,6,32)
|
||||
|
||||
###############
|
||||
# Build rules #
|
||||
###############
|
||||
|
||||
# Standard compilation, with regular output
|
||||
default:
|
||||
@+$(call kernelbuild,modules)
|
||||
|
||||
# Noisy output, for extra debugging
|
||||
noisy:
|
||||
@+$(call kernelbuild,modules,V=1)
|
||||
|
||||
# Silence any output generated
|
||||
silent:
|
||||
@+$(call kernelbuild,modules,>/dev/null)
|
||||
|
||||
# Enable higher warning level
|
||||
checkwarnings: clean
|
||||
@+$(call kernelbuild,modules,W=1)
|
||||
|
||||
# Run sparse static analyzer
|
||||
sparse: clean
|
||||
@+$(call kernelbuild,modules,C=2 CF="-D__CHECK_ENDIAN__ -Wbitwise -Wcontext")
|
||||
|
||||
# Run coccicheck static analyzer
|
||||
ccc: clean
|
||||
@+$(call kernelbuild,modules,coccicheck MODE=report)
|
||||
|
||||
# Build manfiles
|
||||
manfile:
|
||||
@gzip -c ../${DRIVER}.${MANSECTION} > ${DRIVER}.${MANSECTION}.gz
|
||||
|
||||
# Clean the module subdirectories
|
||||
clean:
|
||||
@+$(call kernelbuild,clean)
|
||||
@-rm -rf *.${MANSECTION}.gz *.ko
|
||||
|
||||
# Install the modules and manpage
|
||||
install: default manfile
|
||||
@echo "Copying manpages..."
|
||||
@install -D -m 644 ${DRIVER}.${MANSECTION}.gz ${INSTALL_MOD_PATH}${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz
|
||||
@echo "Installing modules..."
|
||||
@+$(call kernelbuild,modules_install)
|
||||
@echo "Running depmod..."
|
||||
@$(call cmd_depmod)
|
||||
ifeq (${cmd_initrd},)
|
||||
@echo "Unable to update initrd. You may need to do this manually."
|
||||
else
|
||||
@echo "Updating initrd..."
|
||||
-@$(call cmd_initrd)
|
||||
endif
|
||||
|
||||
# Target used by rpmbuild spec file
|
||||
rpm: default manfile
|
||||
@install -D -m 644 ${DRIVER}.${MANSECTION}.gz ${INSTALL_MOD_PATH}${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz
|
||||
@install -D -m 644 ${DRIVER}.ko ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko
|
||||
|
||||
uninstall:
|
||||
rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko;
|
||||
$(call cmd_depmod)
|
||||
ifeq (${cmd_initrd},)
|
||||
@echo "Unable to update initrd. You may need to do this manually."
|
||||
else
|
||||
@echo "Updating initrd..."
|
||||
-@$(call cmd_initrd)
|
||||
endif
|
||||
if [ -e ${INSTALL_MOD_PATH}${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz ] ; then \
|
||||
rm -f ${INSTALL_MOD_PATH}${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz ; \
|
||||
fi;
|
||||
|
||||
########
|
||||
# Help #
|
||||
########
|
||||
help:
|
||||
@echo 'Cleaning targets:'
|
||||
@echo ' clean - Clean files generated by kernel module build'
|
||||
@echo 'Build targets:'
|
||||
@echo ' default - Build module(s) with standard verbosity'
|
||||
@echo ' noisy - Build module(s) with V=1 verbosity -- very noisy'
|
||||
@echo ' silent - Build module(s), squelching all output'
|
||||
@echo 'Static Analysis:'
|
||||
@echo ' checkwarnings - Clean, then build module(s) with W=1 warnings enabled'
|
||||
@echo ' sparse - Clean, then check module(s) using sparse'
|
||||
@echo ' ccc - Clean, then check module(s) using coccicheck'
|
||||
@echo 'Other targets:'
|
||||
@echo ' manfile - Generate a gzipped manpage'
|
||||
@echo ' install - Build then install the module(s) and manpage'
|
||||
@echo ' uninstall - Uninstall the module(s) and manpage'
|
||||
@echo ' help - Display this help message'
|
||||
@echo 'Variables:'
|
||||
@echo ' LINUX_VERSION - Debug tool to force kernel LINUX_VERSION_CODE. Use at your own risk.'
|
||||
@echo ' W=N - Kernel variable for setting warning levels'
|
||||
@echo ' V=N - Kernel variable for setting output verbosity'
|
||||
@echo ' INSTALL_MOD_PATH - Add prefix for the module and manpage installation path'
|
||||
@echo ' INSTALL_MOD_DIR - Use module directory other than updates/drivers/net/ethernet/intel/${DRIVER}'
|
||||
@echo ' KSRC - Specifies the full path to the kernel tree to build against'
|
||||
@echo ' Other variables may be available for tuning make process, see'
|
||||
@echo ' Kernel Kbuild documentation for more information'
|
||||
|
||||
.PHONY: default noisy clean manfile silent sparse ccc install uninstall help
|
||||
|
||||
endif # ifneq($(KERNELRELEASE),)
|
|
@ -0,0 +1 @@
|
|||
i40e.ko external
|
|
@ -0,0 +1,318 @@
|
|||
################################################################################
|
||||
#
|
||||
# Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
# Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# The full GNU General Public License is included in this distribution in
|
||||
# the file called "COPYING".
|
||||
#
|
||||
# Contact Information:
|
||||
# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# common Makefile rules useful for out-of-tree Linux driver builds
|
||||
#
|
||||
# Usage: include common.mk
|
||||
#
|
||||
# After including, you probably want to add a minimum_kver_check call
|
||||
#
|
||||
# Required Variables:
|
||||
# DRIVER
|
||||
# -- Set to the lowercase driver name
|
||||
|
||||
#####################
|
||||
# Helpful functions #
|
||||
#####################
|
||||
|
||||
readlink = $(shell readlink -f ${1})
|
||||
|
||||
# helper functions for converting kernel version to version codes
|
||||
get_kver = $(or $(word ${2},$(subst ., ,${1})),0)
|
||||
get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \
|
||||
[ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \
|
||||
[ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \
|
||||
printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) )
|
||||
|
||||
################
|
||||
# depmod Macro #
|
||||
################
|
||||
|
||||
cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \
|
||||
$(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \
|
||||
-a ${KVER}
|
||||
|
||||
################
|
||||
# dracut Macro #
|
||||
################
|
||||
|
||||
cmd_initrd := $(shell \
|
||||
if which dracut > /dev/null 2>&1 ; then \
|
||||
echo "dracut --force"; \
|
||||
elif which update-initramfs > /dev/null 2>&1 ; then \
|
||||
echo "update-initramfs -u"; \
|
||||
fi )
|
||||
|
||||
#####################
|
||||
# Environment tests #
|
||||
#####################
|
||||
|
||||
DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]")
|
||||
|
||||
ifeq (,${BUILD_KERNEL})
|
||||
BUILD_KERNEL=$(shell uname -r)
|
||||
endif
|
||||
|
||||
# Kernel Search Path
|
||||
# All the places we look for kernel source
|
||||
KSP := /lib/modules/${BUILD_KERNEL}/source \
|
||||
/lib/modules/${BUILD_KERNEL}/build \
|
||||
/usr/src/linux-${BUILD_KERNEL} \
|
||||
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \
|
||||
/usr/src/kernel-headers-${BUILD_KERNEL} \
|
||||
/usr/src/kernel-source-${BUILD_KERNEL} \
|
||||
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
|
||||
/usr/src/linux \
|
||||
/usr/src/kernels/${BUILD_KERNEL} \
|
||||
/usr/src/kernels
|
||||
|
||||
# prune the list down to only values that exist and have an include/linux
|
||||
# sub-directory. We can't use include/config because some older kernels don't
|
||||
# have this.
|
||||
test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir})
|
||||
KSP := $(foreach dir, ${KSP}, ${test_dir})
|
||||
|
||||
# we will use this first valid entry in the search path
|
||||
ifeq (,${KSRC})
|
||||
KSRC := $(firstword ${KSP})
|
||||
endif
|
||||
|
||||
ifeq (,${KSRC})
|
||||
$(warning *** Kernel header files not in any of the expected locations.)
|
||||
$(warning *** Install the appropriate kernel development package, e.g.)
|
||||
$(error kernel-devel, for building kernel modules and try again)
|
||||
else
|
||||
ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC})
|
||||
KOBJ := /lib/modules/${BUILD_KERNEL}/build
|
||||
else
|
||||
KOBJ := ${KSRC}
|
||||
endif
|
||||
endif
|
||||
|
||||
# Version file Search Path
|
||||
VSP := ${KOBJ}/include/generated/utsrelease.h \
|
||||
${KOBJ}/include/linux/utsrelease.h \
|
||||
${KOBJ}/include/linux/version.h \
|
||||
${KOBJ}/include/generated/uapi/linux/version.h \
|
||||
/boot/vmlinuz.version.h
|
||||
|
||||
# Config file Search Path
|
||||
CSP := ${KOBJ}/include/generated/autoconf.h \
|
||||
${KOBJ}/include/linux/autoconf.h \
|
||||
/boot/vmlinuz.autoconf.h
|
||||
|
||||
# System.map Search Path (for depmod)
|
||||
MSP := ${KSRC}/System.map \
|
||||
/boot/System.map-${BUILD_KERNEL}
|
||||
|
||||
# prune the lists down to only files that exist
|
||||
test_file = $(shell [ -f ${file} ] && echo ${file})
|
||||
VSP := $(foreach file, ${VSP}, ${test_file})
|
||||
CSP := $(foreach file, ${CSP}, ${test_file})
|
||||
MSP := $(foreach file, ${MSP}, ${test_file})
|
||||
|
||||
|
||||
# and use the first valid entry in the Search Paths
|
||||
ifeq (,${VERSION_FILE})
|
||||
VERSION_FILE := $(firstword ${VSP})
|
||||
endif
|
||||
|
||||
ifeq (,${CONFIG_FILE})
|
||||
CONFIG_FILE := $(firstword ${CSP})
|
||||
endif
|
||||
|
||||
ifeq (,${SYSTEM_MAP_FILE})
|
||||
SYSTEM_MAP_FILE := $(firstword ${MSP})
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${VERSION_FILE}))
|
||||
$(error Linux kernel source not configured - missing version header file)
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${CONFIG_FILE}))
|
||||
$(error Linux kernel source not configured - missing autoconf.h)
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${SYSTEM_MAP_FILE}))
|
||||
$(warning Missing System.map file - depmod will not check for missing symbols)
|
||||
endif
|
||||
|
||||
#######################
|
||||
# Linux Version Setup #
|
||||
#######################
|
||||
|
||||
# The following command line parameter is intended for development of KCOMPAT
|
||||
# against upstream kernels such as net-next which have broken or non-updated
|
||||
# version codes in their Makefile. They are intended for debugging and
|
||||
# development purpose only so that we can easily test new KCOMPAT early. If you
|
||||
# don't know what this means, you do not need to set this flag. There is no
|
||||
# arcane magic here.
|
||||
|
||||
# Convert LINUX_VERSION into LINUX_VERSION_CODE
|
||||
ifneq (${LINUX_VERSION},)
|
||||
LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3))
|
||||
endif
|
||||
|
||||
# Honor LINUX_VERSION_CODE
|
||||
ifneq (${LINUX_VERSION_CODE},)
|
||||
$(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.)
|
||||
KVER_CODE := ${LINUX_VERSION_CODE}
|
||||
EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE}
|
||||
endif
|
||||
|
||||
# Determine SLE_LOCALVERSION_CODE for SuSE SLE >= 11 (needed by kcompat)
|
||||
# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string
|
||||
# appended to the stable kernel version on which their kernel is based with
|
||||
# additional versioning information (up to 3 numbers), a possible abbreviated
|
||||
# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default
|
||||
# or CONFIG_LOCALVERSION=-999.gdeadbee-default
|
||||
ifeq (1,$(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
|
||||
grep -m 1 CONFIG_SUSE_KERNEL | awk '{ print $$3 }'))
|
||||
|
||||
ifneq (10,$(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
|
||||
grep -m 1 CONFIG_SLE_VERSION | awk '{ print $$3 }'))
|
||||
|
||||
LOCALVERSION := $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
|
||||
grep -m 1 CONFIG_LOCALVERSION | awk '{ print $$3 }' |\
|
||||
cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//')
|
||||
LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1)
|
||||
LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2)
|
||||
LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3)
|
||||
SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \
|
||||
0${LOCALVER_B} \* 256 + 0${LOCALVER_C})
|
||||
EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE}
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += ${CFLAGS_EXTRA}
|
||||
|
||||
# get the kernel version - we use this to find the correct install path
|
||||
KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \
|
||||
awk '{ print $$3 }' | sed 's/\"//g')
|
||||
|
||||
# assume source symlink is the same as build, otherwise adjust KOBJ
|
||||
ifneq (,$(wildcard /lib/modules/${KVER}/build))
|
||||
ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build))
|
||||
KOBJ=/lib/modules/${KVER}/build
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${KVER_CODE},)
|
||||
KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\
|
||||
grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g')
|
||||
endif
|
||||
|
||||
# minimum_kver_check
|
||||
#
|
||||
# helper function to provide uniform output for different drivers to abort the
|
||||
# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)".
|
||||
define _minimum_kver_check
|
||||
ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?"))
|
||||
$$(warning *** Aborting the build.)
|
||||
$$(error This driver is not supported on kernel versions older than ${1}.${2}.${3})
|
||||
endif
|
||||
endef
|
||||
minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3}))
|
||||
|
||||
################
|
||||
# Manual Pages #
|
||||
################
|
||||
|
||||
MANSECTION = 7
|
||||
|
||||
ifeq (,${MANDIR})
|
||||
# find the best place to install the man page
|
||||
MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g')
|
||||
ifneq (,${MANPATH})
|
||||
# test based on inclusion in MANPATH
|
||||
test_dir = $(findstring ${dir}, ${MANPATH})
|
||||
else
|
||||
# no MANPATH, test based on directory existence
|
||||
test_dir = $(shell [ -e ${dir} ] && echo ${dir})
|
||||
endif
|
||||
# our preferred install path
|
||||
# should /usr/local/man be in here ?
|
||||
MANDIR := /usr/share/man /usr/man
|
||||
MANDIR := $(foreach dir, ${MANDIR}, ${test_dir})
|
||||
MANDIR := $(firstword ${MANDIR})
|
||||
endif
|
||||
ifeq (,${MANDIR})
|
||||
# fallback to /usr/man
|
||||
MANDIR := /usr/man
|
||||
endif
|
||||
|
||||
####################
|
||||
# CCFLAGS variable #
|
||||
####################
|
||||
|
||||
# set correct CCFLAGS variable for kernels older than 2.6.24
|
||||
ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?))
|
||||
CCFLAGS_VAR := EXTRA_CFLAGS
|
||||
else
|
||||
CCFLAGS_VAR := ccflags-y
|
||||
endif
|
||||
|
||||
#################
|
||||
# KBUILD_OUTPUT #
|
||||
#################
|
||||
|
||||
# Only set KBUILD_OUTPUT if KOBJ differs from KSRC
|
||||
ifneq (${KSRC},${KOBJ})
|
||||
export KBUILD_OUTPUT ?= ${KOBJ}
|
||||
endif
|
||||
|
||||
############################
|
||||
# Module Install Directory #
|
||||
############################
|
||||
|
||||
# Default to using updates/drivers/net/ethernet/intel/ path, since depmod since
|
||||
# v3.1 defaults to checking updates folder first, and only checking kernels/
|
||||
# and extra afterwards. We use updates instead of kernel/* due to desire to
|
||||
# prevent over-writing built-in modules files.
|
||||
export INSTALL_MOD_DIR ?= updates/drivers/net/ethernet/intel/${DRIVER}
|
||||
|
||||
######################
|
||||
# Kernel Build Macro #
|
||||
######################
|
||||
|
||||
# kernel build function
|
||||
# ${1} is the kernel build target
|
||||
# ${2} may contain any extra rules to pass directly to the sub-make process
|
||||
#
|
||||
# This function is expected to be executed by
|
||||
# @+$(call kernelbuild,<target>,<extra parameters>)
|
||||
# from within a Makefile recipe.
|
||||
#
|
||||
# The following variables are expected to be defined for its use:
|
||||
# GCC_I_SYS -- if set it will enable use of gcc-i-sys.sh wrapper to use -isystem
|
||||
# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS
|
||||
# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable
|
||||
# KSRC -- the location of the kernel source tree to build against
|
||||
# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER
|
||||
#
|
||||
kernelbuild = ${MAKE} $(if ${GCC_I_SYS},CC="${GCC_I_SYS}") \
|
||||
${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \
|
||||
-C "${KSRC}" \
|
||||
CONFIG_${DRIVER_UPPERCASE}=m \
|
||||
M="${CURDIR}" \
|
||||
${2} ${1}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,156 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_ADMINQ_H_
|
||||
#define _I40E_ADMINQ_H_
|
||||
|
||||
#include "i40e_osdep.h"
|
||||
#include "i40e_status.h"
|
||||
#include "i40e_adminq_cmd.h"
|
||||
|
||||
#define I40E_ADMINQ_DESC(R, i) \
|
||||
(&(((struct i40e_aq_desc *)((R).desc_buf.va))[i]))
|
||||
|
||||
#define I40E_ADMINQ_DESC_ALIGNMENT 4096
|
||||
|
||||
struct i40e_adminq_ring {
|
||||
struct i40e_virt_mem dma_head; /* space for dma structures */
|
||||
struct i40e_dma_mem desc_buf; /* descriptor ring memory */
|
||||
struct i40e_virt_mem cmd_buf; /* command buffer memory */
|
||||
|
||||
union {
|
||||
struct i40e_dma_mem *asq_bi;
|
||||
struct i40e_dma_mem *arq_bi;
|
||||
} r;
|
||||
|
||||
u16 count; /* Number of descriptors */
|
||||
u16 rx_buf_len; /* Admin Receive Queue buffer length */
|
||||
|
||||
/* used for interrupt processing */
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
/* used for queue tracking */
|
||||
u32 head;
|
||||
u32 tail;
|
||||
u32 len;
|
||||
u32 bah;
|
||||
u32 bal;
|
||||
};
|
||||
|
||||
/* ASQ transaction details */
|
||||
struct i40e_asq_cmd_details {
|
||||
void *callback; /* cast from type I40E_ADMINQ_CALLBACK */
|
||||
u64 cookie;
|
||||
u16 flags_ena;
|
||||
u16 flags_dis;
|
||||
bool async;
|
||||
bool postpone;
|
||||
struct i40e_aq_desc *wb_desc;
|
||||
};
|
||||
|
||||
#define I40E_ADMINQ_DETAILS(R, i) \
|
||||
(&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i]))
|
||||
|
||||
/* ARQ event information */
|
||||
struct i40e_arq_event_info {
|
||||
struct i40e_aq_desc desc;
|
||||
u16 msg_len;
|
||||
u16 buf_len;
|
||||
u8 *msg_buf;
|
||||
};
|
||||
|
||||
/* Admin Queue information */
|
||||
struct i40e_adminq_info {
|
||||
struct i40e_adminq_ring arq; /* receive queue */
|
||||
struct i40e_adminq_ring asq; /* send queue */
|
||||
u32 asq_cmd_timeout; /* send queue cmd write back timeout*/
|
||||
u16 num_arq_entries; /* receive queue depth */
|
||||
u16 num_asq_entries; /* send queue depth */
|
||||
u16 arq_buf_size; /* receive queue buffer size */
|
||||
u16 asq_buf_size; /* send queue buffer size */
|
||||
u16 fw_maj_ver; /* firmware major version */
|
||||
u16 fw_min_ver; /* firmware minor version */
|
||||
u32 fw_build; /* firmware build number */
|
||||
u16 api_maj_ver; /* api major version */
|
||||
u16 api_min_ver; /* api minor version */
|
||||
|
||||
struct i40e_spinlock asq_spinlock; /* Send queue spinlock */
|
||||
struct i40e_spinlock arq_spinlock; /* Receive queue spinlock */
|
||||
|
||||
/* last status values on send and receive queues */
|
||||
enum i40e_admin_queue_err asq_last_status;
|
||||
enum i40e_admin_queue_err arq_last_status;
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_aq_rc_to_posix - convert errors to user-land codes
|
||||
* aq_ret: AdminQ handler error code can override aq_rc
|
||||
* aq_rc: AdminQ firmware error code to convert
|
||||
**/
|
||||
static INLINE int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
|
||||
{
|
||||
int aq_to_posix[] = {
|
||||
0, /* I40E_AQ_RC_OK */
|
||||
-EPERM, /* I40E_AQ_RC_EPERM */
|
||||
-ENOENT, /* I40E_AQ_RC_ENOENT */
|
||||
-ESRCH, /* I40E_AQ_RC_ESRCH */
|
||||
-EINTR, /* I40E_AQ_RC_EINTR */
|
||||
-EIO, /* I40E_AQ_RC_EIO */
|
||||
-ENXIO, /* I40E_AQ_RC_ENXIO */
|
||||
-E2BIG, /* I40E_AQ_RC_E2BIG */
|
||||
-EAGAIN, /* I40E_AQ_RC_EAGAIN */
|
||||
-ENOMEM, /* I40E_AQ_RC_ENOMEM */
|
||||
-EACCES, /* I40E_AQ_RC_EACCES */
|
||||
-EFAULT, /* I40E_AQ_RC_EFAULT */
|
||||
-EBUSY, /* I40E_AQ_RC_EBUSY */
|
||||
-EEXIST, /* I40E_AQ_RC_EEXIST */
|
||||
-EINVAL, /* I40E_AQ_RC_EINVAL */
|
||||
-ENOTTY, /* I40E_AQ_RC_ENOTTY */
|
||||
-ENOSPC, /* I40E_AQ_RC_ENOSPC */
|
||||
-ENOSYS, /* I40E_AQ_RC_ENOSYS */
|
||||
-ERANGE, /* I40E_AQ_RC_ERANGE */
|
||||
-EPIPE, /* I40E_AQ_RC_EFLUSHED */
|
||||
-ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
|
||||
-EROFS, /* I40E_AQ_RC_EMODE */
|
||||
-EFBIG, /* I40E_AQ_RC_EFBIG */
|
||||
};
|
||||
|
||||
/* aq_rc is invalid if AQ timed out */
|
||||
if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
|
||||
return -ERANGE;
|
||||
|
||||
return aq_to_posix[aq_rc];
|
||||
}
|
||||
|
||||
/* general information */
|
||||
#define I40E_AQ_LARGE_BUF 512
|
||||
#define I40E_ASQ_CMD_TIMEOUT 250 /* msecs */
|
||||
|
||||
void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
|
||||
u16 opcode);
|
||||
|
||||
#endif /* _I40E_ADMINQ_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,55 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_ALLOC_H_
|
||||
#define _I40E_ALLOC_H_
|
||||
|
||||
struct i40e_hw;
|
||||
|
||||
/* Memory allocation types */
|
||||
enum i40e_memory_type {
|
||||
i40e_mem_arq_buf = 0, /* ARQ indirect command buffer */
|
||||
i40e_mem_asq_buf = 1,
|
||||
i40e_mem_atq_buf = 2, /* ATQ indirect command buffer */
|
||||
i40e_mem_arq_ring = 3, /* ARQ descriptor ring */
|
||||
i40e_mem_atq_ring = 4, /* ATQ descriptor ring */
|
||||
i40e_mem_pd = 5, /* Page Descriptor */
|
||||
i40e_mem_bp = 6, /* Backing Page - 4KB */
|
||||
i40e_mem_bp_jumbo = 7, /* Backing Page - > 4KB */
|
||||
i40e_mem_reserved
|
||||
};
|
||||
|
||||
/* prototype for functions used for dynamic memory allocation */
|
||||
i40e_status i40e_allocate_dma_mem(struct i40e_hw *hw,
|
||||
struct i40e_dma_mem *mem,
|
||||
enum i40e_memory_type type,
|
||||
u64 size, u32 alignment);
|
||||
i40e_status i40e_free_dma_mem(struct i40e_hw *hw,
|
||||
struct i40e_dma_mem *mem);
|
||||
i40e_status i40e_allocate_virt_mem(struct i40e_hw *hw,
|
||||
struct i40e_virt_mem *mem,
|
||||
u32 size);
|
||||
i40e_status i40e_free_virt_mem(struct i40e_hw *hw,
|
||||
struct i40e_virt_mem *mem);
|
||||
|
||||
#endif /* _I40E_ALLOC_H_ */
|
|
@ -0,0 +1,814 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "i40e.h"
|
||||
#include "i40e_prototype.h"
|
||||
#include "i40e_client.h"
|
||||
|
||||
static const char i40e_client_interface_version_str[] = I40E_CLIENT_VERSION_STR;
|
||||
static struct i40e_client *registered_client;
|
||||
static LIST_HEAD(i40e_devices);
|
||||
static DEFINE_MUTEX(i40e_device_mutex);
|
||||
|
||||
static int i40e_client_virtchnl_send(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
u32 vf_id, u8 *msg, u16 len);
|
||||
|
||||
static int i40e_client_setup_qvlist(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
struct i40e_qvlist_info *qvlist_info);
|
||||
|
||||
static void i40e_client_request_reset(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
u32 reset_level);
|
||||
|
||||
static int i40e_client_update_vsi_ctxt(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
bool is_vf, u32 vf_id,
|
||||
u32 flag, u32 valid_flag);
|
||||
|
||||
static struct i40e_ops i40e_lan_ops = {
|
||||
.virtchnl_send = i40e_client_virtchnl_send,
|
||||
.setup_qvlist = i40e_client_setup_qvlist,
|
||||
.request_reset = i40e_client_request_reset,
|
||||
.update_vsi_ctxt = i40e_client_update_vsi_ctxt,
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_client_get_params - Get the params that can change at runtime
|
||||
* @vsi: the VSI with the message
|
||||
* @param: clinet param struct
|
||||
*
|
||||
**/
|
||||
static
|
||||
int i40e_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params)
|
||||
{
|
||||
struct i40e_dcbx_config *dcb_cfg = &vsi->back->hw.local_dcbx_config;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
|
||||
u8 tc = dcb_cfg->etscfg.prioritytable[i];
|
||||
u16 qs_handle;
|
||||
|
||||
/* If TC is not enabled for VSI use TC0 for UP */
|
||||
if (!(vsi->tc_config.enabled_tc & BIT(tc)))
|
||||
tc = 0;
|
||||
|
||||
qs_handle = le16_to_cpu(vsi->info.qs_handle[tc]);
|
||||
params->qos.prio_qos[i].tc = tc;
|
||||
params->qos.prio_qos[i].qs_handle = qs_handle;
|
||||
if (qs_handle == I40E_AQ_VSI_QS_HANDLE_INVALID) {
|
||||
dev_err(&vsi->back->pdev->dev, "Invalid queue set handle for TC = %d, vsi id = %d\n",
|
||||
tc, vsi->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
params->mtu = vsi->netdev->mtu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_notify_client_of_vf_msg - call the client vf message callback
|
||||
* @vsi: the VSI with the message
|
||||
* @vf_id: the absolute VF id that sent the message
|
||||
* @msg: message buffer
|
||||
* @len: length of the message
|
||||
*
|
||||
* If there is a client to this VSI, call the client
|
||||
**/
|
||||
void
|
||||
i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id, u8 *msg, u16 len)
|
||||
{
|
||||
struct i40e_pf *pf = vsi->back;
|
||||
struct i40e_client_instance *cdev = pf->cinst;
|
||||
|
||||
if (!cdev || !cdev->client)
|
||||
return;
|
||||
if (!cdev->client->ops || !cdev->client->ops->virtchnl_receive) {
|
||||
dev_dbg(&pf->pdev->dev,
|
||||
"Cannot locate client instance virtual channel receive routine\n");
|
||||
return;
|
||||
}
|
||||
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
|
||||
dev_dbg(&pf->pdev->dev, "Client is not open, abort virtchnl_receive\n");
|
||||
return;
|
||||
}
|
||||
cdev->client->ops->virtchnl_receive(&cdev->lan_info, cdev->client,
|
||||
vf_id, msg, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_notify_client_of_l2_param_changes - call the client notify callback
|
||||
* @vsi: the VSI with l2 param changes
|
||||
*
|
||||
* If there is a client to this VSI, call the client
|
||||
**/
|
||||
void i40e_notify_client_of_l2_param_changes(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct i40e_pf *pf = vsi->back;
|
||||
struct i40e_client_instance *cdev = pf->cinst;
|
||||
struct i40e_params params;
|
||||
|
||||
if (!cdev || !cdev->client)
|
||||
return;
|
||||
if (!cdev->client->ops || !cdev->client->ops->l2_param_change) {
|
||||
dev_dbg(&vsi->back->pdev->dev,
|
||||
"Cannot locate client instance l2_param_change routine\n");
|
||||
return;
|
||||
}
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
i40e_client_get_params(vsi, ¶ms);
|
||||
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
|
||||
dev_dbg(&vsi->back->pdev->dev, "Client is not open, abort l2 param change\n");
|
||||
return;
|
||||
}
|
||||
memcpy(&cdev->lan_info.params, ¶ms, sizeof(struct i40e_params));
|
||||
cdev->client->ops->l2_param_change(&cdev->lan_info, cdev->client,
|
||||
¶ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_release_qvlist - release MSI-X vector mapping for client
|
||||
* @ldev: pointer to L2 context.
|
||||
*
|
||||
**/
|
||||
static void i40e_client_release_qvlist(struct i40e_info *ldev)
|
||||
{
|
||||
struct i40e_qvlist_info *qvlist_info = ldev->qvlist_info;
|
||||
u32 i;
|
||||
|
||||
if (!ldev->qvlist_info)
|
||||
return;
|
||||
|
||||
for (i = 0; i < qvlist_info->num_vectors; i++) {
|
||||
struct i40e_pf *pf = ldev->pf;
|
||||
struct i40e_qv_info *qv_info;
|
||||
u32 reg_idx;
|
||||
|
||||
qv_info = &qvlist_info->qv_info[i];
|
||||
if (!qv_info)
|
||||
continue;
|
||||
reg_idx = I40E_PFINT_LNKLSTN(qv_info->v_idx - 1);
|
||||
wr32(&pf->hw, reg_idx, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
|
||||
}
|
||||
kfree(ldev->qvlist_info);
|
||||
ldev->qvlist_info = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_notify_client_of_netdev_close - call the client close callback
|
||||
* @vsi: the VSI with netdev closed
|
||||
* @reset: true when close called due to a reset pending
|
||||
*
|
||||
* If there is a client to this netdev, call the client with close
|
||||
**/
|
||||
void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset)
|
||||
{
|
||||
struct i40e_pf *pf = vsi->back;
|
||||
struct i40e_client_instance *cdev = pf->cinst;
|
||||
|
||||
if (!cdev || !cdev->client)
|
||||
return;
|
||||
if (!cdev->client->ops || !cdev->client->ops->close) {
|
||||
dev_dbg(&vsi->back->pdev->dev,
|
||||
"Cannot locate client instance close routine\n");
|
||||
return;
|
||||
}
|
||||
cdev->client->ops->close(&cdev->lan_info, cdev->client, reset);
|
||||
clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
|
||||
i40e_client_release_qvlist(&cdev->lan_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_notify_client_of_vf_reset - call the client vf reset callback
|
||||
* @pf: PF device pointer
|
||||
* @vf_id: asolute id of VF being reset
|
||||
*
|
||||
* If there is a client attached to this PF, notify when a VF is reset
|
||||
**/
|
||||
void i40e_notify_client_of_vf_reset(struct i40e_pf *pf, u32 vf_id)
|
||||
{
|
||||
struct i40e_client_instance *cdev = pf->cinst;
|
||||
|
||||
if (!cdev || !cdev->client)
|
||||
return;
|
||||
if (!cdev->client->ops || !cdev->client->ops->vf_reset) {
|
||||
dev_dbg(&pf->pdev->dev,
|
||||
"Cannot locate client instance VF reset routine\n");
|
||||
return;
|
||||
}
|
||||
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
|
||||
dev_dbg(&pf->pdev->dev, "Client is not open, abort vf-reset\n");
|
||||
return;
|
||||
}
|
||||
cdev->client->ops->vf_reset(&cdev->lan_info, cdev->client, vf_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_notify_client_of_vf_enable - call the client vf notification callback
|
||||
* @pf: PF device pointer
|
||||
* @num_vfs: the number of VFs currently enabled, 0 for disable
|
||||
*
|
||||
* If there is a client attached to this PF, call its VF notification routine
|
||||
**/
|
||||
void i40e_notify_client_of_vf_enable(struct i40e_pf *pf, u32 num_vfs)
|
||||
{
|
||||
struct i40e_client_instance *cdev = pf->cinst;
|
||||
|
||||
if (!cdev || !cdev->client)
|
||||
return;
|
||||
if (!cdev->client->ops || !cdev->client->ops->vf_enable) {
|
||||
dev_dbg(&pf->pdev->dev,
|
||||
"Cannot locate client instance VF enable routine\n");
|
||||
return;
|
||||
}
|
||||
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED,
|
||||
&cdev->state)) {
|
||||
dev_dbg(&pf->pdev->dev, "Client is not open, abort vf-enable\n");
|
||||
return;
|
||||
}
|
||||
cdev->client->ops->vf_enable(&cdev->lan_info, cdev->client, num_vfs);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_vf_client_capable - ask the client if it likes the specified VF
|
||||
* @pf: PF device pointer
|
||||
* @vf_id: the VF in question
|
||||
*
|
||||
* If there is a client of the specified type attached to this PF, call
|
||||
* its vf_capable routine
|
||||
**/
|
||||
int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id)
|
||||
{
|
||||
struct i40e_client_instance *cdev = pf->cinst;
|
||||
int capable = false;
|
||||
|
||||
if (!cdev || !cdev->client)
|
||||
goto out;
|
||||
if (!cdev->client->ops || !cdev->client->ops->vf_capable) {
|
||||
dev_dbg(&pf->pdev->dev,
|
||||
"Cannot locate client instance VF capability routine\n");
|
||||
goto out;
|
||||
}
|
||||
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state))
|
||||
goto out;
|
||||
|
||||
capable = cdev->client->ops->vf_capable(&cdev->lan_info,
|
||||
cdev->client,
|
||||
vf_id);
|
||||
out:
|
||||
return capable;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_add_instance - add a client instance struct to the instance list
|
||||
* @pf: pointer to the board struct
|
||||
* @client: pointer to a client struct in the client list.
|
||||
* @existing: if there was already an existing instance
|
||||
*
|
||||
**/
|
||||
static void i40e_client_add_instance(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_client_instance *cdev = NULL;
|
||||
struct netdev_hw_addr *mac = NULL;
|
||||
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
||||
|
||||
if (!registered_client || pf->cinst)
|
||||
return;
|
||||
|
||||
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
|
||||
if (!cdev)
|
||||
return;
|
||||
|
||||
cdev->lan_info.pf = (void *)pf;
|
||||
cdev->lan_info.netdev = vsi->netdev;
|
||||
cdev->lan_info.pcidev = pf->pdev;
|
||||
cdev->lan_info.fid = pf->hw.pf_id;
|
||||
cdev->lan_info.ftype = I40E_CLIENT_FTYPE_PF;
|
||||
cdev->lan_info.hw_addr = pf->hw.hw_addr;
|
||||
cdev->lan_info.ops = &i40e_lan_ops;
|
||||
cdev->lan_info.version.major = I40E_CLIENT_VERSION_MAJOR;
|
||||
cdev->lan_info.version.minor = I40E_CLIENT_VERSION_MINOR;
|
||||
cdev->lan_info.version.build = I40E_CLIENT_VERSION_BUILD;
|
||||
cdev->lan_info.fw_maj_ver = pf->hw.aq.fw_maj_ver;
|
||||
cdev->lan_info.fw_min_ver = pf->hw.aq.fw_min_ver;
|
||||
cdev->lan_info.fw_build = pf->hw.aq.fw_build;
|
||||
set_bit(__I40E_CLIENT_INSTANCE_NONE, &cdev->state);
|
||||
|
||||
if (i40e_client_get_params(vsi, &cdev->lan_info.params)) {
|
||||
kfree(cdev);
|
||||
cdev = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
cdev->lan_info.msix_count = pf->num_iwarp_msix;
|
||||
cdev->lan_info.msix_entries = &pf->msix_entries[pf->iwarp_base_vector];
|
||||
|
||||
mac = list_first_entry(&cdev->lan_info.netdev->dev_addrs.list,
|
||||
struct netdev_hw_addr, list);
|
||||
if (mac)
|
||||
ether_addr_copy(cdev->lan_info.lanmac, mac->addr);
|
||||
else
|
||||
dev_err(&pf->pdev->dev, "MAC address list is empty!\n");
|
||||
|
||||
cdev->client = registered_client;
|
||||
pf->cinst = cdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_del_instance - removes a client instance from the list
|
||||
* @pf: pointer to the board struct
|
||||
*
|
||||
**/
|
||||
static
|
||||
void i40e_client_del_instance(struct i40e_pf *pf)
|
||||
{
|
||||
kfree(pf->cinst);
|
||||
pf->cinst = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_subtask - client maintenance work
|
||||
* @pf: board private structure
|
||||
**/
|
||||
void i40e_client_subtask(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_client *client = registered_client;
|
||||
struct i40e_client_instance *cdev;
|
||||
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
||||
int ret = 0;
|
||||
|
||||
if (!(pf->flags & I40E_FLAG_SERVICE_CLIENT_REQUESTED))
|
||||
return;
|
||||
pf->flags &= ~I40E_FLAG_SERVICE_CLIENT_REQUESTED;
|
||||
cdev = pf->cinst;
|
||||
|
||||
/* If we're down or resetting, just bail */
|
||||
if (test_bit(__I40E_DOWN, &pf->state) ||
|
||||
test_bit(__I40E_CONFIG_BUSY, &pf->state))
|
||||
return;
|
||||
|
||||
if (!client || !cdev)
|
||||
return;
|
||||
|
||||
/* Here we handle client opens. If the client is down, but
|
||||
* the netdev is up, then open the client.
|
||||
*/
|
||||
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
|
||||
if (!test_bit(__I40E_DOWN, &vsi->state) &&
|
||||
client->ops && client->ops->open) {
|
||||
set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
|
||||
ret = client->ops->open(&cdev->lan_info, client);
|
||||
if (ret) {
|
||||
/* Remove failed client instance */
|
||||
clear_bit(__I40E_CLIENT_INSTANCE_OPENED,
|
||||
&cdev->state);
|
||||
i40e_client_del_instance(pf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Likewise for client close. If the client is up, but the netdev
|
||||
* is down, then close the client.
|
||||
*/
|
||||
if (test_bit(__I40E_DOWN, &vsi->state) &&
|
||||
client->ops && client->ops->close) {
|
||||
clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
|
||||
client->ops->close(&cdev->lan_info, client, false);
|
||||
i40e_client_release_qvlist(&cdev->lan_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_lan_add_device - add a lan device struct to the list of lan devices
|
||||
* @pf: pointer to the board struct
|
||||
*
|
||||
* Returns 0 on success or none 0 on error
|
||||
**/
|
||||
int i40e_lan_add_device(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_device *ldev;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&i40e_device_mutex);
|
||||
list_for_each_entry(ldev, &i40e_devices, list) {
|
||||
if (ldev->pf == pf) {
|
||||
ret = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
|
||||
if (!ldev) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ldev->pf = pf;
|
||||
INIT_LIST_HEAD(&ldev->list);
|
||||
list_add(&ldev->list, &i40e_devices);
|
||||
dev_info(&pf->pdev->dev, "Added LAN device PF%d bus=0x%02x dev=0x%02x func=0x%02x\n",
|
||||
pf->hw.pf_id, pf->hw.bus.bus_id,
|
||||
pf->hw.bus.device, pf->hw.bus.func);
|
||||
|
||||
/* Since in some cases register may have happened before a device gets
|
||||
* added, we can schedule a subtask to go initiate the clients if
|
||||
* they can be launched at probe time.
|
||||
*/
|
||||
pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
|
||||
i40e_service_event_schedule(pf);
|
||||
|
||||
out:
|
||||
mutex_unlock(&i40e_device_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_lan_del_device - removes a lan device from the device list
|
||||
* @pf: pointer to the board struct
|
||||
*
|
||||
* Returns 0 on success or non-0 on error
|
||||
**/
|
||||
int i40e_lan_del_device(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_device *ldev, *tmp;
|
||||
int ret = -ENODEV;
|
||||
|
||||
mutex_lock(&i40e_device_mutex);
|
||||
list_for_each_entry_safe(ldev, tmp, &i40e_devices, list) {
|
||||
if (ldev->pf == pf) {
|
||||
dev_info(&pf->pdev->dev, "Deleted LAN device PF%d bus=0x%02x dev=0x%02x func=0x%02x\n",
|
||||
pf->hw.pf_id, pf->hw.bus.bus_id,
|
||||
pf->hw.bus.device, pf->hw.bus.func);
|
||||
list_del(&ldev->list);
|
||||
kfree(ldev);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&i40e_device_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_release - release client specific resources
|
||||
* @client: pointer to the registered client
|
||||
*
|
||||
**/
|
||||
static void i40e_client_release(struct i40e_client *client)
|
||||
{
|
||||
struct i40e_client_instance *cdev;
|
||||
struct i40e_device *ldev;
|
||||
struct i40e_pf *pf;
|
||||
|
||||
mutex_lock(&i40e_device_mutex);
|
||||
list_for_each_entry(ldev, &i40e_devices, list) {
|
||||
pf = ldev->pf;
|
||||
cdev = pf->cinst;
|
||||
if (!cdev)
|
||||
continue;
|
||||
|
||||
while (test_and_set_bit(__I40E_SERVICE_SCHED,
|
||||
&pf->state))
|
||||
usleep_range(500, 1000);
|
||||
|
||||
if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
|
||||
if (client->ops && client->ops->close)
|
||||
client->ops->close(&cdev->lan_info, client,
|
||||
false);
|
||||
i40e_client_release_qvlist(&cdev->lan_info);
|
||||
clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
|
||||
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"Client %s instance for PF id %d closed\n",
|
||||
client->name, pf->hw.pf_id);
|
||||
}
|
||||
/* delete the client instance */
|
||||
i40e_client_del_instance(pf);
|
||||
dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n",
|
||||
client->name);
|
||||
clear_bit(__I40E_SERVICE_SCHED, &pf->state);
|
||||
}
|
||||
mutex_unlock(&i40e_device_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_prepare - prepare client specific resources
|
||||
* @client: pointer to the registered client
|
||||
*
|
||||
**/
|
||||
static void i40e_client_prepare(struct i40e_client *client)
|
||||
{
|
||||
struct i40e_device *ldev;
|
||||
struct i40e_pf *pf;
|
||||
|
||||
mutex_lock(&i40e_device_mutex);
|
||||
list_for_each_entry(ldev, &i40e_devices, list) {
|
||||
pf = ldev->pf;
|
||||
i40e_client_add_instance(pf);
|
||||
/* Start the client subtask */
|
||||
pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
|
||||
i40e_service_event_schedule(pf);
|
||||
}
|
||||
mutex_unlock(&i40e_device_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_virtchnl_send - TBD
|
||||
* @ldev: pointer to L2 context
|
||||
* @client: Client pointer
|
||||
* @vf_id: absolute VF identifier
|
||||
* @msg: message buffer
|
||||
* @len: length of message buffer
|
||||
*
|
||||
* Return 0 on success or < 0 on error
|
||||
**/
|
||||
static int i40e_client_virtchnl_send(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
u32 vf_id, u8 *msg, u16 len)
|
||||
{
|
||||
struct i40e_pf *pf = ldev->pf;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
i40e_status err;
|
||||
|
||||
err = i40e_aq_send_msg_to_vf(hw, vf_id, I40E_VIRTCHNL_OP_IWARP,
|
||||
I40E_SUCCESS, msg, len, NULL);
|
||||
if (err)
|
||||
dev_err(&pf->pdev->dev, "Unable to send iWarp message to VF, error %d, aq status %d\n",
|
||||
err, hw->aq.asq_last_status);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_setup_qvlist
|
||||
* @ldev: pointer to L2 context.
|
||||
* @client: Client pointer.
|
||||
* @qv_info: queue and vector list
|
||||
*
|
||||
* Return 0 on success or < 0 on error
|
||||
**/
|
||||
static int i40e_client_setup_qvlist(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
struct i40e_qvlist_info *qvlist_info)
|
||||
{
|
||||
struct i40e_pf *pf = ldev->pf;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
struct i40e_qv_info *qv_info;
|
||||
u32 v_idx, i, reg_idx, reg;
|
||||
u32 size;
|
||||
|
||||
size = sizeof(struct i40e_qvlist_info) +
|
||||
(sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1));
|
||||
ldev->qvlist_info = kzalloc(size, GFP_KERNEL);
|
||||
ldev->qvlist_info->num_vectors = qvlist_info->num_vectors;
|
||||
|
||||
for (i = 0; i < qvlist_info->num_vectors; i++) {
|
||||
qv_info = &qvlist_info->qv_info[i];
|
||||
if (!qv_info)
|
||||
continue;
|
||||
v_idx = qv_info->v_idx;
|
||||
|
||||
/* Validate vector id belongs to this client */
|
||||
if ((v_idx >= (pf->iwarp_base_vector + pf->num_iwarp_msix)) ||
|
||||
(v_idx < pf->iwarp_base_vector))
|
||||
goto err;
|
||||
|
||||
ldev->qvlist_info->qv_info[i] = *qv_info;
|
||||
reg_idx = I40E_PFINT_LNKLSTN(v_idx - 1);
|
||||
|
||||
if (qv_info->ceq_idx == I40E_QUEUE_INVALID_IDX) {
|
||||
/* Special case - No CEQ mapped on this vector */
|
||||
wr32(hw, reg_idx, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK);
|
||||
} else {
|
||||
reg = (qv_info->ceq_idx &
|
||||
I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK) |
|
||||
(I40E_QUEUE_TYPE_PE_CEQ <<
|
||||
I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT);
|
||||
wr32(hw, reg_idx, reg);
|
||||
|
||||
reg = (I40E_PFINT_CEQCTL_CAUSE_ENA_MASK |
|
||||
(v_idx << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT) |
|
||||
(qv_info->itr_idx <<
|
||||
I40E_PFINT_CEQCTL_ITR_INDX_SHIFT) |
|
||||
(I40E_QUEUE_END_OF_LIST <<
|
||||
I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT));
|
||||
wr32(hw, I40E_PFINT_CEQCTL(qv_info->ceq_idx), reg);
|
||||
}
|
||||
if (qv_info->aeq_idx != I40E_QUEUE_INVALID_IDX) {
|
||||
reg = (I40E_PFINT_AEQCTL_CAUSE_ENA_MASK |
|
||||
(v_idx << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT) |
|
||||
(qv_info->itr_idx <<
|
||||
I40E_PFINT_AEQCTL_ITR_INDX_SHIFT));
|
||||
|
||||
wr32(hw, I40E_PFINT_AEQCTL, reg);
|
||||
}
|
||||
}
|
||||
/* Mitigate sync problems with iwarp VF driver */
|
||||
i40e_flush(hw);
|
||||
return 0;
|
||||
err:
|
||||
kfree(ldev->qvlist_info);
|
||||
ldev->qvlist_info = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_request_reset
|
||||
* @ldev: pointer to L2 context.
|
||||
* @client: Client pointer.
|
||||
* @level: reset level
|
||||
**/
|
||||
static void i40e_client_request_reset(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
u32 reset_level)
|
||||
{
|
||||
struct i40e_pf *pf = ldev->pf;
|
||||
|
||||
switch (reset_level) {
|
||||
case I40E_CLIENT_RESET_LEVEL_PF:
|
||||
set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
|
||||
break;
|
||||
case I40E_CLIENT_RESET_LEVEL_CORE:
|
||||
set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
|
||||
break;
|
||||
default:
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"Client for PF id %d requested an unsupported reset: %d.\n",
|
||||
pf->hw.pf_id, reset_level);
|
||||
break;
|
||||
}
|
||||
|
||||
i40e_service_event_schedule(pf);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_client_update_vsi_ctxt
|
||||
* @ldev: pointer to L2 context.
|
||||
* @client: Client pointer.
|
||||
* @is_vf: if this for the VF
|
||||
* @vf_id: if is_vf true this carries the vf_id
|
||||
* @flag: Any device level setting that needs to be done for PE
|
||||
* @valid_flag: Bits in this match up and enable changing of flag bits
|
||||
*
|
||||
* Return 0 on success or < 0 on error
|
||||
**/
|
||||
static int i40e_client_update_vsi_ctxt(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
bool is_vf, u32 vf_id,
|
||||
u32 flag, u32 valid_flag)
|
||||
{
|
||||
struct i40e_pf *pf = ldev->pf;
|
||||
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
||||
struct i40e_vsi_context ctxt;
|
||||
bool update = true;
|
||||
i40e_status err;
|
||||
|
||||
/* TODO: for now do not allow setting VF's VSI setting */
|
||||
if (is_vf)
|
||||
return -EINVAL;
|
||||
|
||||
ctxt.seid = pf->main_vsi_seid;
|
||||
ctxt.pf_num = pf->hw.pf_id;
|
||||
err = i40e_aq_get_vsi_params(&pf->hw, &ctxt, NULL);
|
||||
ctxt.flags = I40E_AQ_VSI_TYPE_PF;
|
||||
if (err) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"couldn't get PF vsi config, err %s aq_err %s\n",
|
||||
i40e_stat_str(&pf->hw, err),
|
||||
i40e_aq_str(&pf->hw,
|
||||
pf->hw.aq.asq_last_status));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if ((valid_flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE) &&
|
||||
(flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE)) {
|
||||
ctxt.info.valid_sections =
|
||||
cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
|
||||
ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;
|
||||
} else if ((valid_flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE) &&
|
||||
!(flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE)) {
|
||||
ctxt.info.valid_sections =
|
||||
cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
|
||||
ctxt.info.queueing_opt_flags &= ~I40E_AQ_VSI_QUE_OPT_TCP_ENA;
|
||||
} else {
|
||||
update = false;
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"Client for PF id %d request an unsupported Config: %x.\n",
|
||||
pf->hw.pf_id, flag);
|
||||
}
|
||||
|
||||
if (update) {
|
||||
err = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
|
||||
if (err) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"update VSI ctxt for PE failed, err %s aq_err %s\n",
|
||||
i40e_stat_str(&pf->hw, err),
|
||||
i40e_aq_str(&pf->hw,
|
||||
pf->hw.aq.asq_last_status));
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_register_client - Register a i40e client driver with the L2 driver
|
||||
* @client: pointer to the i40e_client struct
|
||||
*
|
||||
* Returns 0 on success or non-0 on error
|
||||
**/
|
||||
int i40e_register_client(struct i40e_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!client) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strlen(client->name) == 0) {
|
||||
pr_info("i40e: Failed to register client with no name\n");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (registered_client) {
|
||||
pr_info("i40e: Client %s has already been registered!\n",
|
||||
client->name);
|
||||
ret = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((client->version.major != I40E_CLIENT_VERSION_MAJOR) ||
|
||||
(client->version.minor != I40E_CLIENT_VERSION_MINOR)) {
|
||||
pr_info("i40e: Failed to register client %s due to mismatched client interface version\n",
|
||||
client->name);
|
||||
pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
|
||||
client->version.major, client->version.minor,
|
||||
client->version.build,
|
||||
i40e_client_interface_version_str);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
registered_client = client;
|
||||
|
||||
i40e_client_prepare(client);
|
||||
|
||||
pr_info("i40e: Registered client %s\n", client->name);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
//EXPORT_SYMBOL(i40e_register_client);
|
||||
|
||||
/**
|
||||
* i40e_unregister_client - Unregister a i40e client driver with the L2 driver
|
||||
* @client: pointer to the i40e_client struct
|
||||
*
|
||||
* Returns 0 on success or non-0 on error
|
||||
**/
|
||||
int i40e_unregister_client(struct i40e_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (registered_client != client) {
|
||||
pr_info("i40e: Client %s has not been registered\n",
|
||||
client->name);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
registered_client = NULL;
|
||||
/* When a unregister request comes through we would have to send
|
||||
* a close for each of the client instances that were opened.
|
||||
* client_release function is called to handle this.
|
||||
*/
|
||||
i40e_client_release(client);
|
||||
|
||||
pr_info("i40e: Unregistered client %s\n", client->name);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
//EXPORT_SYMBOL(i40e_unregister_client);
|
|
@ -0,0 +1,224 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_CLIENT_H_
|
||||
#define _I40E_CLIENT_H_
|
||||
|
||||
#define I40E_CLIENT_STR_LENGTH 10
|
||||
|
||||
/* Client interface version should be updated anytime there is a change in the
|
||||
* existing APIs or data structures.
|
||||
*/
|
||||
#define I40E_CLIENT_VERSION_MAJOR 0
|
||||
#define I40E_CLIENT_VERSION_MINOR 01
|
||||
#define I40E_CLIENT_VERSION_BUILD 00
|
||||
#define I40E_CLIENT_VERSION_STR \
|
||||
__stringify(I40E_CLIENT_VERSION_MAJOR) "." \
|
||||
__stringify(I40E_CLIENT_VERSION_MINOR) "." \
|
||||
__stringify(I40E_CLIENT_VERSION_BUILD)
|
||||
|
||||
struct i40e_client_version {
|
||||
u8 major;
|
||||
u8 minor;
|
||||
u8 build;
|
||||
u8 rsvd;
|
||||
};
|
||||
|
||||
enum i40e_client_state {
|
||||
__I40E_CLIENT_NULL,
|
||||
__I40E_CLIENT_REGISTERED
|
||||
};
|
||||
|
||||
enum i40e_client_instance_state {
|
||||
__I40E_CLIENT_INSTANCE_NONE,
|
||||
__I40E_CLIENT_INSTANCE_OPENED,
|
||||
};
|
||||
|
||||
struct i40e_ops;
|
||||
struct i40e_client;
|
||||
|
||||
/* HW does not define a type value for AEQ; only for RX/TX and CEQ.
|
||||
* In order for us to keep the interface simple, SW will define a
|
||||
* unique type value for AEQ.
|
||||
*/
|
||||
#define I40E_QUEUE_TYPE_PE_AEQ 0x80
|
||||
#define I40E_QUEUE_INVALID_IDX 0xFFFF
|
||||
|
||||
struct i40e_qv_info {
|
||||
u32 v_idx; /* msix_vector */
|
||||
u16 ceq_idx;
|
||||
u16 aeq_idx;
|
||||
u8 itr_idx;
|
||||
};
|
||||
|
||||
struct i40e_qvlist_info {
|
||||
u32 num_vectors;
|
||||
struct i40e_qv_info qv_info[1];
|
||||
};
|
||||
|
||||
#define I40E_CLIENT_MSIX_ALL 0xFFFFFFFF
|
||||
|
||||
/* set of LAN parameters useful for clients managed by LAN */
|
||||
|
||||
/* Struct to hold per priority info */
|
||||
struct i40e_prio_qos_params {
|
||||
u16 qs_handle; /* qs handle for prio */
|
||||
u8 tc; /* TC mapped to prio */
|
||||
u8 reserved;
|
||||
};
|
||||
|
||||
#define I40E_CLIENT_MAX_USER_PRIORITY 8
|
||||
/* Struct to hold Client QoS */
|
||||
struct i40e_qos_params {
|
||||
struct i40e_prio_qos_params prio_qos[I40E_CLIENT_MAX_USER_PRIORITY];
|
||||
};
|
||||
|
||||
struct i40e_params {
|
||||
struct i40e_qos_params qos;
|
||||
u16 mtu;
|
||||
};
|
||||
|
||||
/* Structure to hold Lan device info for a client device */
|
||||
struct i40e_info {
|
||||
struct i40e_client_version version;
|
||||
u8 lanmac[6];
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pcidev;
|
||||
u8 __iomem *hw_addr;
|
||||
u8 fid; /* function id, PF id or VF id */
|
||||
#define I40E_CLIENT_FTYPE_PF 0
|
||||
#define I40E_CLIENT_FTYPE_VF 1
|
||||
u8 ftype; /* function type, PF or VF */
|
||||
void *pf;
|
||||
|
||||
/* All L2 params that could change during the life span of the PF
|
||||
* and needs to be communicated to the client when they change
|
||||
*/
|
||||
struct i40e_qvlist_info *qvlist_info;
|
||||
struct i40e_params params;
|
||||
struct i40e_ops *ops;
|
||||
|
||||
u16 msix_count; /* number of msix vectors*/
|
||||
/* Array down below will be dynamically allocated based on msix_count */
|
||||
struct msix_entry *msix_entries;
|
||||
u16 itr_index; /* Which ITR index the PE driver is suppose to use */
|
||||
u16 fw_maj_ver; /* firmware major version */
|
||||
u16 fw_min_ver; /* firmware minor version */
|
||||
u32 fw_build; /* firmware build number */
|
||||
};
|
||||
|
||||
#define I40E_CLIENT_RESET_LEVEL_PF 1
|
||||
#define I40E_CLIENT_RESET_LEVEL_CORE 2
|
||||
#define I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE BIT(1)
|
||||
|
||||
struct i40e_ops {
|
||||
/* setup_q_vector_list enables queues with a particular vector */
|
||||
int (*setup_qvlist)(struct i40e_info *ldev, struct i40e_client *client,
|
||||
struct i40e_qvlist_info *qv_info);
|
||||
|
||||
int (*virtchnl_send)(struct i40e_info *ldev, struct i40e_client *client,
|
||||
u32 vf_id, u8 *msg, u16 len);
|
||||
|
||||
/* If the PE Engine is unresponsive, RDMA driver can request a reset.
|
||||
* The level helps determine the level of reset being requested.
|
||||
*/
|
||||
void (*request_reset)(struct i40e_info *ldev,
|
||||
struct i40e_client *client, u32 level);
|
||||
|
||||
/* API for the RDMA driver to set certain VSI flags that control
|
||||
* PE Engine.
|
||||
*/
|
||||
int (*update_vsi_ctxt)(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
bool is_vf, u32 vf_id,
|
||||
u32 flag, u32 valid_flag);
|
||||
};
|
||||
|
||||
struct i40e_client_ops {
|
||||
/* Should be called from register_client() or whenever PF is ready
|
||||
* to create a specific client instance.
|
||||
*/
|
||||
int (*open)(struct i40e_info *ldev, struct i40e_client *client);
|
||||
|
||||
/* Should be called when netdev is unavailable or when unregister
|
||||
* call comes in. If the close is happenening due to a reset being
|
||||
* triggered set the reset bit to true.
|
||||
*/
|
||||
void (*close)(struct i40e_info *ldev, struct i40e_client *client,
|
||||
bool reset);
|
||||
|
||||
/* called when some l2 managed parameters changes - mtu */
|
||||
void (*l2_param_change)(struct i40e_info *ldev,
|
||||
struct i40e_client *client,
|
||||
struct i40e_params *params);
|
||||
|
||||
int (*virtchnl_receive)(struct i40e_info *ldev,
|
||||
struct i40e_client *client, u32 vf_id,
|
||||
u8 *msg, u16 len);
|
||||
|
||||
/* called when a VF is reset by the PF */
|
||||
void (*vf_reset)(struct i40e_info *ldev,
|
||||
struct i40e_client *client, u32 vf_id);
|
||||
|
||||
/* called when the number of VFs changes */
|
||||
void (*vf_enable)(struct i40e_info *ldev,
|
||||
struct i40e_client *client, u32 num_vfs);
|
||||
|
||||
/* returns true if VF is capable of specified offload */
|
||||
int (*vf_capable)(struct i40e_info *ldev,
|
||||
struct i40e_client *client, u32 vf_id);
|
||||
};
|
||||
|
||||
/* Client device */
|
||||
struct i40e_client_instance {
|
||||
struct list_head list;
|
||||
struct i40e_info lan_info;
|
||||
struct i40e_client *client;
|
||||
unsigned long state;
|
||||
};
|
||||
|
||||
struct i40e_client {
|
||||
struct list_head list; /* list of registered clients */
|
||||
char name[I40E_CLIENT_STR_LENGTH];
|
||||
struct i40e_client_version version;
|
||||
unsigned long state; /* client state */
|
||||
atomic_t ref_cnt; /* Count of all the client devices of this kind */
|
||||
u32 flags;
|
||||
#define I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE BIT(0)
|
||||
#define I40E_TX_FLAGS_NOTIFY_OTHER_EVENTS BIT(2)
|
||||
u8 type;
|
||||
#define I40E_CLIENT_IWARP 0
|
||||
/* client ops provided by the client */
|
||||
const struct i40e_client_ops *ops;
|
||||
};
|
||||
|
||||
static inline bool i40e_client_is_registered(struct i40e_client *client)
|
||||
{
|
||||
return test_bit(__I40E_CLIENT_REGISTERED, &client->state);
|
||||
}
|
||||
|
||||
/* used by clients */
|
||||
int i40e_register_client(struct i40e_client *client);
|
||||
int i40e_unregister_client(struct i40e_client *client);
|
||||
|
||||
#endif /* _I40E_CLIENT_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,968 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_adminq.h"
|
||||
#include "i40e_prototype.h"
|
||||
#include "i40e_dcb.h"
|
||||
|
||||
/**
|
||||
* i40e_get_dcbx_status
|
||||
* @hw: pointer to the hw struct
|
||||
* @status: Embedded DCBX Engine Status
|
||||
*
|
||||
* Get the DCBX status from the Firmware
|
||||
**/
|
||||
i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!status)
|
||||
return I40E_ERR_PARAM;
|
||||
|
||||
reg = rd32(hw, I40E_PRTDCB_GENS);
|
||||
*status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
|
||||
I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
|
||||
|
||||
return I40E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_etscfg_tlv
|
||||
* @tlv: IEEE 802.1Qaz ETS CFG TLV
|
||||
* @dcbcfg: Local store to update ETS CFG data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz ETS CFG TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
struct i40e_dcb_ets_config *etscfg;
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
u16 offset = 0;
|
||||
u8 priority;
|
||||
int i;
|
||||
|
||||
/* First Octet post subtype
|
||||
* --------------------------
|
||||
* |will-|CBS | Re- | Max |
|
||||
* |ing | |served| TCs |
|
||||
* --------------------------
|
||||
* |1bit | 1bit|3 bits|3bits|
|
||||
*/
|
||||
etscfg = &dcbcfg->etscfg;
|
||||
etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
|
||||
I40E_IEEE_ETS_WILLING_SHIFT);
|
||||
etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
|
||||
I40E_IEEE_ETS_CBS_SHIFT);
|
||||
etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
|
||||
I40E_IEEE_ETS_MAXTC_SHIFT);
|
||||
|
||||
/* Move offset to Priority Assignment Table */
|
||||
offset++;
|
||||
|
||||
/* Priority Assignment Table (4 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 |
|
||||
* -----------------------------------------
|
||||
* |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
|
||||
* -----------------------------------------
|
||||
* Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_1_SHIFT);
|
||||
etscfg->prioritytable[i * 2] = priority;
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_0_SHIFT);
|
||||
etscfg->prioritytable[i * 2 + 1] = priority;
|
||||
offset++;
|
||||
}
|
||||
|
||||
/* TC Bandwidth Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
etscfg->tcbwtable[i] = buf[offset++];
|
||||
|
||||
/* TSA Assignment Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
etscfg->tsatable[i] = buf[offset++];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_etsrec_tlv
|
||||
* @tlv: IEEE 802.1Qaz ETS REC TLV
|
||||
* @dcbcfg: Local store to update ETS REC data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz ETS REC TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
u16 offset = 0;
|
||||
u8 priority;
|
||||
int i;
|
||||
|
||||
/* Move offset to priority table */
|
||||
offset++;
|
||||
|
||||
/* Priority Assignment Table (4 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 |
|
||||
* -----------------------------------------
|
||||
* |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
|
||||
* -----------------------------------------
|
||||
* Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_1_SHIFT);
|
||||
dcbcfg->etsrec.prioritytable[i*2] = priority;
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_0_SHIFT);
|
||||
dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
|
||||
offset++;
|
||||
}
|
||||
|
||||
/* TC Bandwidth Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
|
||||
|
||||
/* TSA Assignment Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
dcbcfg->etsrec.tsatable[i] = buf[offset++];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_pfccfg_tlv
|
||||
* @tlv: IEEE 802.1Qaz PFC CFG TLV
|
||||
* @dcbcfg: Local store to update PFC CFG data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz PFC CFG TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
|
||||
/* ----------------------------------------
|
||||
* |will-|MBC | Re- | PFC | PFC Enable |
|
||||
* |ing | |served| cap | |
|
||||
* -----------------------------------------
|
||||
* |1bit | 1bit|2 bits|4bits| 1 octet |
|
||||
*/
|
||||
dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
|
||||
I40E_IEEE_PFC_WILLING_SHIFT);
|
||||
dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
|
||||
I40E_IEEE_PFC_MBC_SHIFT);
|
||||
dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
|
||||
I40E_IEEE_PFC_CAP_SHIFT);
|
||||
dcbcfg->pfc.pfcenable = buf[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_app_tlv
|
||||
* @tlv: IEEE 802.1Qaz APP TLV
|
||||
* @dcbcfg: Local store to update APP PRIO data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz APP PRIO TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u16 typelength;
|
||||
u16 offset = 0;
|
||||
u16 length;
|
||||
int i = 0;
|
||||
u8 *buf;
|
||||
|
||||
typelength = ntohs(tlv->typelength);
|
||||
length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
buf = tlv->tlvinfo;
|
||||
|
||||
/* The App priority table starts 5 octets after TLV header */
|
||||
length -= (sizeof(tlv->ouisubtype) + 1);
|
||||
|
||||
/* Move offset to App Priority Table */
|
||||
offset++;
|
||||
|
||||
/* Application Priority Table (3 octets)
|
||||
* Octets:| 1 | 2 | 3 |
|
||||
* -----------------------------------------
|
||||
* |Priority|Rsrvd| Sel | Protocol ID |
|
||||
* -----------------------------------------
|
||||
* Bits:|23 21|20 19|18 16|15 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
while (offset < length) {
|
||||
dcbcfg->app[i].priority = (u8)((buf[offset] &
|
||||
I40E_IEEE_APP_PRIO_MASK) >>
|
||||
I40E_IEEE_APP_PRIO_SHIFT);
|
||||
dcbcfg->app[i].selector = (u8)((buf[offset] &
|
||||
I40E_IEEE_APP_SEL_MASK) >>
|
||||
I40E_IEEE_APP_SEL_SHIFT);
|
||||
dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
|
||||
buf[offset + 2];
|
||||
/* Move to next app */
|
||||
offset += 3;
|
||||
i++;
|
||||
if (i >= I40E_DCBX_MAX_APPS)
|
||||
break;
|
||||
}
|
||||
|
||||
dcbcfg->numapps = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_etsrec_tlv
|
||||
* @tlv: IEEE 802.1Qaz TLV
|
||||
* @dcbcfg: Local store to update ETS REC data
|
||||
*
|
||||
* Get the TLV subtype and send it to parsing function
|
||||
* based on the subtype value
|
||||
**/
|
||||
static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u32 ouisubtype;
|
||||
u8 subtype;
|
||||
|
||||
ouisubtype = ntohl(tlv->ouisubtype);
|
||||
subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
|
||||
I40E_LLDP_TLV_SUBTYPE_SHIFT);
|
||||
switch (subtype) {
|
||||
case I40E_IEEE_SUBTYPE_ETS_CFG:
|
||||
i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_IEEE_SUBTYPE_ETS_REC:
|
||||
i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_IEEE_SUBTYPE_PFC_CFG:
|
||||
i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_IEEE_SUBTYPE_APP_PRI:
|
||||
i40e_parse_ieee_app_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_cee_pgcfg_tlv
|
||||
* @tlv: CEE DCBX PG CFG TLV
|
||||
* @dcbcfg: Local store to update ETS CFG data
|
||||
*
|
||||
* Parses CEE DCBX PG CFG TLV
|
||||
**/
|
||||
static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
struct i40e_dcb_ets_config *etscfg;
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
u16 offset = 0;
|
||||
u8 priority;
|
||||
int i;
|
||||
|
||||
etscfg = &dcbcfg->etscfg;
|
||||
|
||||
if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
|
||||
etscfg->willing = 1;
|
||||
|
||||
etscfg->cbs = 0;
|
||||
/* Priority Group Table (4 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 |
|
||||
* -----------------------------------------
|
||||
* |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
|
||||
* -----------------------------------------
|
||||
* Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
|
||||
I40E_CEE_PGID_PRIO_1_SHIFT);
|
||||
etscfg->prioritytable[i * 2] = priority;
|
||||
priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
|
||||
I40E_CEE_PGID_PRIO_0_SHIFT);
|
||||
etscfg->prioritytable[i * 2 + 1] = priority;
|
||||
offset++;
|
||||
}
|
||||
|
||||
/* PG Percentage Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
etscfg->tcbwtable[i] = buf[offset++];
|
||||
|
||||
/* Number of TCs supported (1 octet) */
|
||||
etscfg->maxtcs = buf[offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_cee_pfccfg_tlv
|
||||
* @tlv: CEE DCBX PFC CFG TLV
|
||||
* @dcbcfg: Local store to update PFC CFG data
|
||||
*
|
||||
* Parses CEE DCBX PFC CFG TLV
|
||||
**/
|
||||
static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
|
||||
if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
|
||||
dcbcfg->pfc.willing = 1;
|
||||
|
||||
/* ------------------------
|
||||
* | PFC Enable | PFC TCs |
|
||||
* ------------------------
|
||||
* | 1 octet | 1 octet |
|
||||
*/
|
||||
dcbcfg->pfc.pfcenable = buf[0];
|
||||
dcbcfg->pfc.pfccap = buf[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_cee_app_tlv
|
||||
* @tlv: CEE DCBX APP TLV
|
||||
* @dcbcfg: Local store to update APP PRIO data
|
||||
*
|
||||
* Parses CEE DCBX APP PRIO TLV
|
||||
**/
|
||||
static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u16 length, typelength, offset = 0;
|
||||
struct i40e_cee_app_prio *app;
|
||||
u8 i;
|
||||
|
||||
typelength = ntohs(tlv->hdr.typelen);
|
||||
length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
|
||||
dcbcfg->numapps = length / sizeof(*app);
|
||||
if (!dcbcfg->numapps)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dcbcfg->numapps; i++) {
|
||||
u8 up, selector;
|
||||
|
||||
app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
|
||||
for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
|
||||
if (app->prio_map & BIT(up))
|
||||
break;
|
||||
}
|
||||
dcbcfg->app[i].priority = up;
|
||||
|
||||
/* Get Selector from lower 2 bits, and convert to IEEE */
|
||||
selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
|
||||
switch (selector) {
|
||||
case I40E_CEE_APP_SEL_ETHTYPE:
|
||||
dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
|
||||
break;
|
||||
case I40E_CEE_APP_SEL_TCPIP:
|
||||
dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
|
||||
break;
|
||||
default:
|
||||
/* Keep selector as it is for unknown types */
|
||||
dcbcfg->app[i].selector = selector;
|
||||
}
|
||||
|
||||
dcbcfg->app[i].protocolid = ntohs(app->protocol);
|
||||
/* Move to next app */
|
||||
offset += sizeof(*app);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_cee_tlv
|
||||
* @tlv: CEE DCBX TLV
|
||||
* @dcbcfg: Local store to update DCBX config data
|
||||
*
|
||||
* Get the TLV subtype and send it to parsing function
|
||||
* based on the subtype value
|
||||
**/
|
||||
static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u16 len, tlvlen, sublen, typelength;
|
||||
struct i40e_cee_feat_tlv *sub_tlv;
|
||||
u8 subtype, feat_tlv_count = 0;
|
||||
u32 ouisubtype;
|
||||
|
||||
ouisubtype = ntohl(tlv->ouisubtype);
|
||||
subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
|
||||
I40E_LLDP_TLV_SUBTYPE_SHIFT);
|
||||
/* Return if not CEE DCBX */
|
||||
if (subtype != I40E_CEE_DCBX_TYPE)
|
||||
return;
|
||||
|
||||
typelength = ntohs(tlv->typelength);
|
||||
tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
|
||||
sizeof(struct i40e_cee_ctrl_tlv);
|
||||
/* Return if no CEE DCBX Feature TLVs */
|
||||
if (tlvlen <= len)
|
||||
return;
|
||||
|
||||
sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
|
||||
while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
|
||||
typelength = ntohs(sub_tlv->hdr.typelen);
|
||||
sublen = (u16)((typelength &
|
||||
I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
|
||||
I40E_LLDP_TLV_TYPE_SHIFT);
|
||||
switch (subtype) {
|
||||
case I40E_CEE_SUBTYPE_PG_CFG:
|
||||
i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_CEE_SUBTYPE_PFC_CFG:
|
||||
i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_CEE_SUBTYPE_APP_PRI:
|
||||
i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
return; /* Invalid Sub-type return */
|
||||
}
|
||||
feat_tlv_count++;
|
||||
/* Move to next sub TLV */
|
||||
sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
|
||||
sizeof(sub_tlv->hdr.typelen) +
|
||||
sublen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_org_tlv
|
||||
* @tlv: Organization specific TLV
|
||||
* @dcbcfg: Local store to update ETS REC data
|
||||
*
|
||||
* Currently only IEEE 802.1Qaz TLV is supported, all others
|
||||
* will be returned
|
||||
**/
|
||||
static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u32 ouisubtype;
|
||||
u32 oui;
|
||||
|
||||
ouisubtype = ntohl(tlv->ouisubtype);
|
||||
oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
|
||||
I40E_LLDP_TLV_OUI_SHIFT);
|
||||
switch (oui) {
|
||||
case I40E_IEEE_8021QAZ_OUI:
|
||||
i40e_parse_ieee_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_CEE_DCBX_OUI:
|
||||
i40e_parse_cee_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_lldp_to_dcb_config
|
||||
* @lldpmib: LLDPDU to be parsed
|
||||
* @dcbcfg: store for LLDPDU data
|
||||
*
|
||||
* Parse DCB configuration from the LLDPDU
|
||||
**/
|
||||
i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
i40e_status ret = I40E_SUCCESS;
|
||||
struct i40e_lldp_org_tlv *tlv;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u16 typelength;
|
||||
u16 offset = 0;
|
||||
|
||||
if (!lldpmib || !dcbcfg)
|
||||
return I40E_ERR_PARAM;
|
||||
|
||||
/* set to the start of LLDPDU */
|
||||
lldpmib += ETH_HLEN;
|
||||
tlv = (struct i40e_lldp_org_tlv *)lldpmib;
|
||||
while (1) {
|
||||
typelength = ntohs(tlv->typelength);
|
||||
type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
|
||||
I40E_LLDP_TLV_TYPE_SHIFT);
|
||||
length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
offset += sizeof(typelength) + length;
|
||||
|
||||
/* END TLV or beyond LLDPDU size */
|
||||
if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
|
||||
break;
|
||||
|
||||
switch (type) {
|
||||
case I40E_TLV_TYPE_ORG:
|
||||
i40e_parse_org_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next TLV */
|
||||
tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
|
||||
sizeof(tlv->typelength) +
|
||||
length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_get_dcb_config
|
||||
* @hw: pointer to the hw struct
|
||||
* @mib_type: mib type for the query
|
||||
* @bridgetype: bridge type for the query (remote)
|
||||
* @dcbcfg: store for LLDPDU data
|
||||
*
|
||||
* Query DCB configuration from the Firmware
|
||||
**/
|
||||
i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
|
||||
u8 bridgetype,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
i40e_status ret = I40E_SUCCESS;
|
||||
struct i40e_virt_mem mem;
|
||||
u8 *lldpmib;
|
||||
|
||||
/* Allocate the LLDPDU */
|
||||
ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lldpmib = (u8 *)mem.va;
|
||||
ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
|
||||
(void *)lldpmib, I40E_LLDPDU_SIZE,
|
||||
NULL, NULL, NULL);
|
||||
if (ret)
|
||||
goto free_mem;
|
||||
|
||||
/* Parse LLDP MIB to get dcb configuration */
|
||||
ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
|
||||
|
||||
free_mem:
|
||||
i40e_free_virt_mem(hw, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_cee_to_dcb_v1_config
|
||||
* @cee_cfg: pointer to CEE v1 response configuration struct
|
||||
* @dcbcfg: DCB configuration struct
|
||||
*
|
||||
* Convert CEE v1 configuration from firmware to DCB configuration
|
||||
**/
|
||||
static void i40e_cee_to_dcb_v1_config(
|
||||
struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status);
|
||||
u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
|
||||
u8 i, tc, err;
|
||||
|
||||
/* CEE PG data to ETS config */
|
||||
dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
|
||||
|
||||
/* Note that the FW creates the oper_prio_tc nibbles reversed
|
||||
* from those in the CEE Priority Group sub-TLV.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
tc = (u8)((cee_cfg->oper_prio_tc[i] &
|
||||
I40E_CEE_PGID_PRIO_0_MASK) >>
|
||||
I40E_CEE_PGID_PRIO_0_SHIFT);
|
||||
dcbcfg->etscfg.prioritytable[i*2] = tc;
|
||||
tc = (u8)((cee_cfg->oper_prio_tc[i] &
|
||||
I40E_CEE_PGID_PRIO_1_MASK) >>
|
||||
I40E_CEE_PGID_PRIO_1_SHIFT);
|
||||
dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
|
||||
}
|
||||
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
|
||||
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
|
||||
if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
|
||||
/* Map it to next empty TC */
|
||||
dcbcfg->etscfg.prioritytable[i] =
|
||||
cee_cfg->oper_num_tc - 1;
|
||||
dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
|
||||
} else {
|
||||
dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
|
||||
}
|
||||
}
|
||||
|
||||
/* CEE PFC data to ETS config */
|
||||
dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
|
||||
dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
|
||||
|
||||
status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
|
||||
I40E_AQC_CEE_APP_STATUS_SHIFT;
|
||||
err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
|
||||
/* Add APPs if Error is False */
|
||||
if (!err) {
|
||||
/* CEE operating configuration supports FCoE/iSCSI/FIP only */
|
||||
dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
|
||||
|
||||
/* FCoE APP */
|
||||
dcbcfg->app[0].priority =
|
||||
(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
|
||||
I40E_AQC_CEE_APP_FCOE_SHIFT;
|
||||
dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
|
||||
dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
|
||||
|
||||
/* iSCSI APP */
|
||||
dcbcfg->app[1].priority =
|
||||
(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
|
||||
I40E_AQC_CEE_APP_ISCSI_SHIFT;
|
||||
dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
|
||||
dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
|
||||
|
||||
/* FIP APP */
|
||||
dcbcfg->app[2].priority =
|
||||
(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
|
||||
I40E_AQC_CEE_APP_FIP_SHIFT;
|
||||
dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
|
||||
dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_cee_to_dcb_config
|
||||
* @cee_cfg: pointer to CEE configuration struct
|
||||
* @dcbcfg: DCB configuration struct
|
||||
*
|
||||
* Convert CEE configuration from firmware to DCB configuration
|
||||
**/
|
||||
static void i40e_cee_to_dcb_config(
|
||||
struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status);
|
||||
u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
|
||||
u8 i, tc, err, sync, oper;
|
||||
|
||||
/* CEE PG data to ETS config */
|
||||
dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
|
||||
|
||||
/* Note that the FW creates the oper_prio_tc nibbles reversed
|
||||
* from those in the CEE Priority Group sub-TLV.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
tc = (u8)((cee_cfg->oper_prio_tc[i] &
|
||||
I40E_CEE_PGID_PRIO_0_MASK) >>
|
||||
I40E_CEE_PGID_PRIO_0_SHIFT);
|
||||
dcbcfg->etscfg.prioritytable[i*2] = tc;
|
||||
tc = (u8)((cee_cfg->oper_prio_tc[i] &
|
||||
I40E_CEE_PGID_PRIO_1_MASK) >>
|
||||
I40E_CEE_PGID_PRIO_1_SHIFT);
|
||||
dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
|
||||
}
|
||||
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
|
||||
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
|
||||
if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
|
||||
/* Map it to next empty TC */
|
||||
dcbcfg->etscfg.prioritytable[i] =
|
||||
cee_cfg->oper_num_tc - 1;
|
||||
dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
|
||||
} else {
|
||||
dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
|
||||
}
|
||||
}
|
||||
|
||||
/* CEE PFC data to ETS config */
|
||||
dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
|
||||
dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
|
||||
|
||||
i = 0;
|
||||
status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
|
||||
I40E_AQC_CEE_FCOE_STATUS_SHIFT;
|
||||
err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
|
||||
sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
|
||||
oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
|
||||
/* Add FCoE APP if Error is False and Oper/Sync is True */
|
||||
if (!err && sync && oper) {
|
||||
/* FCoE APP */
|
||||
dcbcfg->app[i].priority =
|
||||
(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
|
||||
I40E_AQC_CEE_APP_FCOE_SHIFT;
|
||||
dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
|
||||
dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
|
||||
i++;
|
||||
}
|
||||
|
||||
status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
|
||||
I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
|
||||
err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
|
||||
sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
|
||||
oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
|
||||
/* Add iSCSI APP if Error is False and Oper/Sync is True */
|
||||
if (!err && sync && oper) {
|
||||
/* iSCSI APP */
|
||||
dcbcfg->app[i].priority =
|
||||
(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
|
||||
I40E_AQC_CEE_APP_ISCSI_SHIFT;
|
||||
dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
|
||||
dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
|
||||
i++;
|
||||
}
|
||||
|
||||
status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
|
||||
I40E_AQC_CEE_FIP_STATUS_SHIFT;
|
||||
err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
|
||||
sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
|
||||
oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
|
||||
/* Add FIP APP if Error is False and Oper/Sync is True */
|
||||
if (!err && sync && oper) {
|
||||
/* FIP APP */
|
||||
dcbcfg->app[i].priority =
|
||||
(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
|
||||
I40E_AQC_CEE_APP_FIP_SHIFT;
|
||||
dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
|
||||
dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
|
||||
i++;
|
||||
}
|
||||
dcbcfg->numapps = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_get_ieee_dcb_config
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Get IEEE mode DCB configuration from the Firmware
|
||||
**/
|
||||
static i40e_status i40e_get_ieee_dcb_config(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret = I40E_SUCCESS;
|
||||
|
||||
/* IEEE mode */
|
||||
hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
|
||||
/* Get Local DCB Config */
|
||||
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
|
||||
&hw->local_dcbx_config);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Get Remote DCB Config */
|
||||
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
|
||||
I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
|
||||
&hw->remote_dcbx_config);
|
||||
/* Don't treat ENOENT as an error for Remote MIBs */
|
||||
if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
|
||||
ret = I40E_SUCCESS;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_get_dcb_config
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Get DCB configuration from the Firmware
|
||||
**/
|
||||
i40e_status i40e_get_dcb_config(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret = I40E_SUCCESS;
|
||||
struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
|
||||
struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
|
||||
|
||||
/* If Firmware version < v4.33 on X710/XL710, IEEE only */
|
||||
if ((hw->mac.type == I40E_MAC_XL710) &&
|
||||
(((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
|
||||
(hw->aq.fw_maj_ver < 4)))
|
||||
return i40e_get_ieee_dcb_config(hw);
|
||||
|
||||
/* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
|
||||
if ((hw->mac.type == I40E_MAC_XL710) &&
|
||||
((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
|
||||
ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
|
||||
sizeof(cee_v1_cfg), NULL);
|
||||
if (ret == I40E_SUCCESS) {
|
||||
/* CEE mode */
|
||||
hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
|
||||
hw->local_dcbx_config.tlv_status =
|
||||
LE16_TO_CPU(cee_v1_cfg.tlv_status);
|
||||
i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
|
||||
&hw->local_dcbx_config);
|
||||
}
|
||||
} else {
|
||||
ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
|
||||
sizeof(cee_cfg), NULL);
|
||||
if (ret == I40E_SUCCESS) {
|
||||
/* CEE mode */
|
||||
hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
|
||||
hw->local_dcbx_config.tlv_status =
|
||||
LE32_TO_CPU(cee_cfg.tlv_status);
|
||||
i40e_cee_to_dcb_config(&cee_cfg,
|
||||
&hw->local_dcbx_config);
|
||||
}
|
||||
}
|
||||
|
||||
/* CEE mode not enabled try querying IEEE data */
|
||||
if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
|
||||
return i40e_get_ieee_dcb_config(hw);
|
||||
|
||||
if (ret != I40E_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/* Get CEE DCB Desired Config */
|
||||
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
|
||||
&hw->desired_dcbx_config);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Get Remote DCB Config */
|
||||
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
|
||||
I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
|
||||
&hw->remote_dcbx_config);
|
||||
/* Don't treat ENOENT as an error for Remote MIBs */
|
||||
if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
|
||||
ret = I40E_SUCCESS;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_init_dcb
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Update DCB configuration from the Firmware
|
||||
**/
|
||||
i40e_status i40e_init_dcb(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret = I40E_SUCCESS;
|
||||
struct i40e_lldp_variables lldp_cfg;
|
||||
u8 adminstatus = 0;
|
||||
|
||||
if (!hw->func_caps.dcb)
|
||||
return ret;
|
||||
|
||||
/* Read LLDP NVM area */
|
||||
ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get the LLDP AdminStatus for the current port */
|
||||
adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
|
||||
adminstatus &= 0xF;
|
||||
|
||||
/* LLDP agent disabled */
|
||||
if (!adminstatus) {
|
||||
hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get DCBX status */
|
||||
ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check the DCBX Status */
|
||||
switch (hw->dcbx_status) {
|
||||
case I40E_DCBX_STATUS_DONE:
|
||||
case I40E_DCBX_STATUS_IN_PROGRESS:
|
||||
/* Get current DCBX configuration */
|
||||
ret = i40e_get_dcb_config(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case I40E_DCBX_STATUS_DISABLED:
|
||||
return ret;
|
||||
case I40E_DCBX_STATUS_NOT_STARTED:
|
||||
case I40E_DCBX_STATUS_MULTIPLE_PEERS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Configure the LLDP MIB change event */
|
||||
ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_read_lldp_cfg - read LLDP Configuration data from NVM
|
||||
* @hw: pointer to the HW structure
|
||||
* @lldp_cfg: pointer to hold lldp configuration variables
|
||||
*
|
||||
* Reads the LLDP configuration data from NVM
|
||||
**/
|
||||
i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw,
|
||||
struct i40e_lldp_variables *lldp_cfg)
|
||||
{
|
||||
i40e_status ret = I40E_SUCCESS;
|
||||
u32 offset = (2 * I40E_NVM_LLDP_CFG_PTR);
|
||||
|
||||
if (!lldp_cfg)
|
||||
return I40E_ERR_PARAM;
|
||||
|
||||
ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
|
||||
if (ret != I40E_SUCCESS)
|
||||
goto err_lldp_cfg;
|
||||
|
||||
ret = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR, offset,
|
||||
sizeof(struct i40e_lldp_variables),
|
||||
(u8 *)lldp_cfg,
|
||||
true, NULL);
|
||||
i40e_release_nvm(hw);
|
||||
|
||||
err_lldp_cfg:
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_DCB_H_
|
||||
#define _I40E_DCB_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
||||
#define I40E_DCBX_STATUS_NOT_STARTED 0
|
||||
#define I40E_DCBX_STATUS_IN_PROGRESS 1
|
||||
#define I40E_DCBX_STATUS_DONE 2
|
||||
#define I40E_DCBX_STATUS_MULTIPLE_PEERS 3
|
||||
#define I40E_DCBX_STATUS_DISABLED 7
|
||||
|
||||
#define I40E_TLV_TYPE_END 0
|
||||
#define I40E_TLV_TYPE_ORG 127
|
||||
|
||||
#define I40E_IEEE_8021QAZ_OUI 0x0080C2
|
||||
#define I40E_IEEE_SUBTYPE_ETS_CFG 9
|
||||
#define I40E_IEEE_SUBTYPE_ETS_REC 10
|
||||
#define I40E_IEEE_SUBTYPE_PFC_CFG 11
|
||||
#define I40E_IEEE_SUBTYPE_APP_PRI 12
|
||||
|
||||
#define I40E_CEE_DCBX_OUI 0x001b21
|
||||
#define I40E_CEE_DCBX_TYPE 2
|
||||
|
||||
#define I40E_CEE_SUBTYPE_CTRL 1
|
||||
#define I40E_CEE_SUBTYPE_PG_CFG 2
|
||||
#define I40E_CEE_SUBTYPE_PFC_CFG 3
|
||||
#define I40E_CEE_SUBTYPE_APP_PRI 4
|
||||
|
||||
#define I40E_CEE_MAX_FEAT_TYPE 3
|
||||
/* Defines for LLDP TLV header */
|
||||
#define I40E_LLDP_TLV_LEN_SHIFT 0
|
||||
#define I40E_LLDP_TLV_LEN_MASK (0x01FF << I40E_LLDP_TLV_LEN_SHIFT)
|
||||
#define I40E_LLDP_TLV_TYPE_SHIFT 9
|
||||
#define I40E_LLDP_TLV_TYPE_MASK (0x7F << I40E_LLDP_TLV_TYPE_SHIFT)
|
||||
#define I40E_LLDP_TLV_SUBTYPE_SHIFT 0
|
||||
#define I40E_LLDP_TLV_SUBTYPE_MASK (0xFF << I40E_LLDP_TLV_SUBTYPE_SHIFT)
|
||||
#define I40E_LLDP_TLV_OUI_SHIFT 8
|
||||
#define I40E_LLDP_TLV_OUI_MASK (0xFFFFFF << I40E_LLDP_TLV_OUI_SHIFT)
|
||||
|
||||
/* Defines for IEEE ETS TLV */
|
||||
#define I40E_IEEE_ETS_MAXTC_SHIFT 0
|
||||
#define I40E_IEEE_ETS_MAXTC_MASK (0x7 << I40E_IEEE_ETS_MAXTC_SHIFT)
|
||||
#define I40E_IEEE_ETS_CBS_SHIFT 6
|
||||
#define I40E_IEEE_ETS_CBS_MASK BIT(I40E_IEEE_ETS_CBS_SHIFT)
|
||||
#define I40E_IEEE_ETS_WILLING_SHIFT 7
|
||||
#define I40E_IEEE_ETS_WILLING_MASK BIT(I40E_IEEE_ETS_WILLING_SHIFT)
|
||||
#define I40E_IEEE_ETS_PRIO_0_SHIFT 0
|
||||
#define I40E_IEEE_ETS_PRIO_0_MASK (0x7 << I40E_IEEE_ETS_PRIO_0_SHIFT)
|
||||
#define I40E_IEEE_ETS_PRIO_1_SHIFT 4
|
||||
#define I40E_IEEE_ETS_PRIO_1_MASK (0x7 << I40E_IEEE_ETS_PRIO_1_SHIFT)
|
||||
#define I40E_CEE_PGID_PRIO_0_SHIFT 0
|
||||
#define I40E_CEE_PGID_PRIO_0_MASK (0xF << I40E_CEE_PGID_PRIO_0_SHIFT)
|
||||
#define I40E_CEE_PGID_PRIO_1_SHIFT 4
|
||||
#define I40E_CEE_PGID_PRIO_1_MASK (0xF << I40E_CEE_PGID_PRIO_1_SHIFT)
|
||||
#define I40E_CEE_PGID_STRICT 15
|
||||
|
||||
/* Defines for IEEE TSA types */
|
||||
#define I40E_IEEE_TSA_STRICT 0
|
||||
#define I40E_IEEE_TSA_ETS 2
|
||||
|
||||
/* Defines for IEEE PFC TLV */
|
||||
#define I40E_IEEE_PFC_CAP_SHIFT 0
|
||||
#define I40E_IEEE_PFC_CAP_MASK (0xF << I40E_IEEE_PFC_CAP_SHIFT)
|
||||
#define I40E_IEEE_PFC_MBC_SHIFT 6
|
||||
#define I40E_IEEE_PFC_MBC_MASK BIT(I40E_IEEE_PFC_MBC_SHIFT)
|
||||
#define I40E_IEEE_PFC_WILLING_SHIFT 7
|
||||
#define I40E_IEEE_PFC_WILLING_MASK BIT(I40E_IEEE_PFC_WILLING_SHIFT)
|
||||
|
||||
/* Defines for IEEE APP TLV */
|
||||
#define I40E_IEEE_APP_SEL_SHIFT 0
|
||||
#define I40E_IEEE_APP_SEL_MASK (0x7 << I40E_IEEE_APP_SEL_SHIFT)
|
||||
#define I40E_IEEE_APP_PRIO_SHIFT 5
|
||||
#define I40E_IEEE_APP_PRIO_MASK (0x7 << I40E_IEEE_APP_PRIO_SHIFT)
|
||||
|
||||
/* TLV definitions for preparing MIB */
|
||||
#define I40E_TLV_ID_CHASSIS_ID 0
|
||||
#define I40E_TLV_ID_PORT_ID 1
|
||||
#define I40E_TLV_ID_TIME_TO_LIVE 2
|
||||
#define I40E_IEEE_TLV_ID_ETS_CFG 3
|
||||
#define I40E_IEEE_TLV_ID_ETS_REC 4
|
||||
#define I40E_IEEE_TLV_ID_PFC_CFG 5
|
||||
#define I40E_IEEE_TLV_ID_APP_PRI 6
|
||||
#define I40E_TLV_ID_END_OF_LLDPPDU 7
|
||||
#define I40E_TLV_ID_START I40E_IEEE_TLV_ID_ETS_CFG
|
||||
|
||||
#define I40E_IEEE_ETS_TLV_LENGTH 25
|
||||
#define I40E_IEEE_PFC_TLV_LENGTH 6
|
||||
#define I40E_IEEE_APP_TLV_LENGTH 11
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* IEEE 802.1AB LLDP Organization specific TLV */
|
||||
struct i40e_lldp_org_tlv {
|
||||
__be16 typelength;
|
||||
__be32 ouisubtype;
|
||||
u8 tlvinfo[1];
|
||||
};
|
||||
|
||||
struct i40e_cee_tlv_hdr {
|
||||
__be16 typelen;
|
||||
u8 operver;
|
||||
u8 maxver;
|
||||
};
|
||||
|
||||
struct i40e_cee_ctrl_tlv {
|
||||
struct i40e_cee_tlv_hdr hdr;
|
||||
__be32 seqno;
|
||||
__be32 ackno;
|
||||
};
|
||||
|
||||
struct i40e_cee_feat_tlv {
|
||||
struct i40e_cee_tlv_hdr hdr;
|
||||
u8 en_will_err; /* Bits: |En|Will|Err|Reserved(5)| */
|
||||
#define I40E_CEE_FEAT_TLV_ENABLE_MASK 0x80
|
||||
#define I40E_CEE_FEAT_TLV_WILLING_MASK 0x40
|
||||
#define I40E_CEE_FEAT_TLV_ERR_MASK 0x20
|
||||
u8 subtype;
|
||||
u8 tlvinfo[1];
|
||||
};
|
||||
|
||||
struct i40e_cee_app_prio {
|
||||
__be16 protocol;
|
||||
u8 upper_oui_sel; /* Bits: |Upper OUI(6)|Selector(2)| */
|
||||
#define I40E_CEE_APP_SELECTOR_MASK 0x03
|
||||
__be16 lower_oui;
|
||||
u8 prio_map;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
i40e_status i40e_get_dcbx_status(struct i40e_hw *hw,
|
||||
u16 *status);
|
||||
i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
|
||||
struct i40e_dcbx_config *dcbcfg);
|
||||
i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
|
||||
u8 bridgetype,
|
||||
struct i40e_dcbx_config *dcbcfg);
|
||||
i40e_status i40e_get_dcb_config(struct i40e_hw *hw);
|
||||
i40e_status i40e_init_dcb(struct i40e_hw *hw);
|
||||
|
||||
#endif /* _I40E_DCB_H_ */
|
|
@ -0,0 +1,321 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DCB
|
||||
#include "i40e.h"
|
||||
#include <net/dcbnl.h>
|
||||
|
||||
#ifdef HAVE_DCBNL_IEEE
|
||||
/**
|
||||
* i40e_get_pfc_delay - retrieve PFC Link Delay
|
||||
* @hw: pointer to hardware struct
|
||||
* @delay: holds the PFC Link delay value
|
||||
*
|
||||
* Returns PFC Link Delay from the PRTDCB_GENC.PFCLDA
|
||||
**/
|
||||
static void i40e_get_pfc_delay(struct i40e_hw *hw, u16 *delay)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = rd32(hw, I40E_PRTDCB_GENC);
|
||||
*delay = (u16)((val & I40E_PRTDCB_GENC_PFCLDA_MASK) >>
|
||||
I40E_PRTDCB_GENC_PFCLDA_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_ieee_getets - retrieve local IEEE ETS configuration
|
||||
* @netdev: the corresponding netdev
|
||||
* @ets: structure to hold the ETS information
|
||||
*
|
||||
* Returns local IEEE ETS configuration
|
||||
**/
|
||||
static int i40e_dcbnl_ieee_getets(struct net_device *dev,
|
||||
struct ieee_ets *ets)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
|
||||
if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
|
||||
return -EINVAL;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
ets->willing = dcbxcfg->etscfg.willing;
|
||||
ets->ets_cap = dcbxcfg->etscfg.maxtcs;
|
||||
ets->cbs = dcbxcfg->etscfg.cbs;
|
||||
memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable,
|
||||
sizeof(ets->tc_tx_bw));
|
||||
memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable,
|
||||
sizeof(ets->tc_rx_bw));
|
||||
memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable,
|
||||
sizeof(ets->tc_tsa));
|
||||
memcpy(ets->prio_tc, dcbxcfg->etscfg.prioritytable,
|
||||
sizeof(ets->prio_tc));
|
||||
memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable,
|
||||
sizeof(ets->tc_reco_bw));
|
||||
memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable,
|
||||
sizeof(ets->tc_reco_tsa));
|
||||
memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prioritytable,
|
||||
sizeof(ets->reco_prio_tc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_ieee_getpfc - retrieve local IEEE PFC configuration
|
||||
* @netdev: the corresponding netdev
|
||||
* @ets: structure to hold the PFC information
|
||||
*
|
||||
* Returns local IEEE PFC configuration
|
||||
**/
|
||||
static int i40e_dcbnl_ieee_getpfc(struct net_device *dev,
|
||||
struct ieee_pfc *pfc)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
int i;
|
||||
|
||||
if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
|
||||
return -EINVAL;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
pfc->pfc_cap = dcbxcfg->pfc.pfccap;
|
||||
pfc->pfc_en = dcbxcfg->pfc.pfcenable;
|
||||
pfc->mbc = dcbxcfg->pfc.mbc;
|
||||
i40e_get_pfc_delay(hw, &pfc->delay);
|
||||
|
||||
/* Get Requests/Indicatiosn */
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
|
||||
pfc->requests[i] = pf->stats.priority_xoff_tx[i];
|
||||
pfc->indications[i] = pf->stats.priority_xoff_rx[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_getdcbx - retrieve current DCBx capability
|
||||
* @netdev: the corresponding netdev
|
||||
*
|
||||
* Returns DCBx capability features
|
||||
**/
|
||||
static u8 i40e_dcbnl_getdcbx(struct net_device *dev)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
|
||||
return pf->dcbx_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_get_perm_hw_addr - MAC address used by DCBx
|
||||
* @netdev: the corresponding netdev
|
||||
*
|
||||
* Returns the SAN MAC address used for LLDP exchange
|
||||
**/
|
||||
static void i40e_dcbnl_get_perm_hw_addr(struct net_device *dev,
|
||||
u8 *perm_addr)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
int i, j;
|
||||
|
||||
memset(perm_addr, 0xff, MAX_ADDR_LEN);
|
||||
|
||||
for (i = 0; i < dev->addr_len; i++)
|
||||
perm_addr[i] = pf->hw.mac.perm_addr[i];
|
||||
|
||||
for (j = 0; j < dev->addr_len; j++, i++)
|
||||
perm_addr[i] = pf->hw.mac.san_addr[j];
|
||||
}
|
||||
|
||||
static const struct dcbnl_rtnl_ops dcbnl_ops = {
|
||||
.ieee_getets = i40e_dcbnl_ieee_getets,
|
||||
.ieee_getpfc = i40e_dcbnl_ieee_getpfc,
|
||||
.getdcbx = i40e_dcbnl_getdcbx,
|
||||
.getpermhwaddr = i40e_dcbnl_get_perm_hw_addr,
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_set_all - set all the apps and ieee data from DCBx config
|
||||
* @vsi: the corresponding vsi
|
||||
*
|
||||
* Set up all the IEEE APPs in the DCBNL App Table and generate event for
|
||||
* other settings
|
||||
**/
|
||||
void i40e_dcbnl_set_all(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct net_device *dev = vsi->netdev;
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
struct dcb_app sapp;
|
||||
u8 prio, tc_map;
|
||||
int i;
|
||||
|
||||
/* DCB not enabled */
|
||||
if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
|
||||
return;
|
||||
|
||||
/* MFP mode but not an iSCSI PF so return */
|
||||
if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi))
|
||||
return;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
|
||||
/* Set up all the App TLVs if DCBx is negotiated */
|
||||
for (i = 0; i < dcbxcfg->numapps; i++) {
|
||||
prio = dcbxcfg->app[i].priority;
|
||||
tc_map = BIT(dcbxcfg->etscfg.prioritytable[prio]);
|
||||
|
||||
/* Add APP only if the TC is enabled for this VSI */
|
||||
if (tc_map & vsi->tc_config.enabled_tc) {
|
||||
sapp.selector = dcbxcfg->app[i].selector;
|
||||
sapp.protocol = dcbxcfg->app[i].protocolid;
|
||||
sapp.priority = prio;
|
||||
dcb_ieee_setapp(dev, &sapp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DCBNL_IEEE_DELAPP
|
||||
/* Notify user-space of the changes */
|
||||
dcbnl_ieee_notify(dev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_vsi_del_app - Delete APP for given VSI
|
||||
* @vsi: the corresponding vsi
|
||||
* @app: APP to delete
|
||||
*
|
||||
* Delete given APP from the DCBNL APP table for given
|
||||
* VSI
|
||||
**/
|
||||
static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi,
|
||||
struct i40e_dcb_app_priority_table *app)
|
||||
{
|
||||
struct net_device *dev = vsi->netdev;
|
||||
struct dcb_app sapp;
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
sapp.selector = app->selector;
|
||||
sapp.protocol = app->protocolid;
|
||||
sapp.priority = app->priority;
|
||||
return dcb_ieee_delapp(dev, &sapp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_del_app - Delete APP on all VSIs
|
||||
* @pf: the corresponding PF
|
||||
* @app: APP to delete
|
||||
*
|
||||
* Delete given APP from all the VSIs for given PF
|
||||
**/
|
||||
static void i40e_dcbnl_del_app(struct i40e_pf *pf,
|
||||
struct i40e_dcb_app_priority_table *app)
|
||||
{
|
||||
int v, err;
|
||||
|
||||
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
||||
if (pf->vsi[v] && pf->vsi[v]->netdev) {
|
||||
err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app);
|
||||
dev_dbg(&pf->pdev->dev, "Deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n",
|
||||
pf->vsi[v]->seid, err, app->selector,
|
||||
app->protocolid, app->priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_find_app - Search APP in given DCB config
|
||||
* @cfg: DCBX configuration data
|
||||
* @app: APP to search for
|
||||
*
|
||||
* Find given APP in the DCB configuration
|
||||
**/
|
||||
static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg,
|
||||
struct i40e_dcb_app_priority_table *app)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cfg->numapps; i++) {
|
||||
if (app->selector == cfg->app[i].selector &&
|
||||
app->protocolid == cfg->app[i].protocolid &&
|
||||
app->priority == cfg->app[i].priority)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_flush_apps - Delete all removed APPs
|
||||
* @pf: the corresponding PF
|
||||
* @old_cfg: old DCBX configuration data
|
||||
* @new_cfg: new DCBX configuration data
|
||||
*
|
||||
* Find and delete all APPs that are not present in the passed
|
||||
* DCB configuration
|
||||
**/
|
||||
void i40e_dcbnl_flush_apps(struct i40e_pf *pf,
|
||||
struct i40e_dcbx_config *old_cfg,
|
||||
struct i40e_dcbx_config *new_cfg)
|
||||
{
|
||||
struct i40e_dcb_app_priority_table app;
|
||||
int i;
|
||||
|
||||
/* MFP mode but not an iSCSI PF so return */
|
||||
if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi))
|
||||
return;
|
||||
|
||||
for (i = 0; i < old_cfg->numapps; i++) {
|
||||
app = old_cfg->app[i];
|
||||
/* The APP is not available anymore delete it */
|
||||
if (!i40e_dcbnl_find_app(new_cfg, &app))
|
||||
i40e_dcbnl_del_app(pf, &app);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_setup - DCBNL setup
|
||||
* @vsi: the corresponding vsi
|
||||
*
|
||||
* Set up DCBNL ops and initial APP TLVs
|
||||
**/
|
||||
void i40e_dcbnl_setup(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct net_device *dev = vsi->netdev;
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
|
||||
/* Not DCB capable */
|
||||
if (!(pf->flags & I40E_FLAG_DCB_CAPABLE))
|
||||
return;
|
||||
|
||||
dev->dcbnl_ops = &dcbnl_ops;
|
||||
|
||||
/* Set initial IEEE DCB settings */
|
||||
i40e_dcbnl_set_all(vsi);
|
||||
}
|
||||
#endif /* HAVE_DCBNL_IEEE */
|
||||
#endif /* CONFIG_DCB */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,51 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#define _I40E_DEVIDS_H_
|
||||
|
||||
/* Device IDs */
|
||||
#define I40E_DEV_ID_SFP_XL710 0x1572
|
||||
#define I40E_DEV_ID_QEMU 0x1574
|
||||
#define I40E_DEV_ID_KX_B 0x1580
|
||||
#define I40E_DEV_ID_KX_C 0x1581
|
||||
#define I40E_DEV_ID_QSFP_A 0x1583
|
||||
#define I40E_DEV_ID_QSFP_B 0x1584
|
||||
#define I40E_DEV_ID_QSFP_C 0x1585
|
||||
#define I40E_DEV_ID_10G_BASE_T 0x1586
|
||||
#define I40E_DEV_ID_20G_KR2 0x1587
|
||||
#define I40E_DEV_ID_20G_KR2_A 0x1588
|
||||
#define I40E_DEV_ID_10G_BASE_T4 0x1589
|
||||
#define I40E_DEV_ID_25G_B 0x158A
|
||||
#define I40E_DEV_ID_25G_SFP28 0x158B
|
||||
#define I40E_DEV_ID_X722_A0 0x374C
|
||||
#define I40E_DEV_ID_KX_X722 0x37CE
|
||||
#define I40E_DEV_ID_QSFP_X722 0x37CF
|
||||
#define I40E_DEV_ID_SFP_X722 0x37D0
|
||||
#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
|
||||
#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
|
||||
#define I40E_DEV_ID_SFP_I_X722 0x37D3
|
||||
|
||||
#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
|
||||
(d) == I40E_DEV_ID_QSFP_B || \
|
||||
(d) == I40E_DEV_ID_QSFP_C)
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_diag.h"
|
||||
#include "i40e_prototype.h"
|
||||
|
||||
/**
|
||||
* i40e_diag_reg_pattern_test
|
||||
* @hw: pointer to the hw struct
|
||||
* @reg: reg to be tested
|
||||
* @mask: bits to be touched
|
||||
**/
|
||||
static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw,
|
||||
u32 reg, u32 mask)
|
||||
{
|
||||
const u32 patterns[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
|
||||
u32 pat, val, orig_val;
|
||||
int i;
|
||||
|
||||
orig_val = rd32(hw, reg);
|
||||
for (i = 0; i < ARRAY_SIZE(patterns); i++) {
|
||||
pat = patterns[i];
|
||||
wr32(hw, reg, (pat & mask));
|
||||
val = rd32(hw, reg);
|
||||
if ((val & mask) != (pat & mask)) {
|
||||
#ifdef ETHTOOL_TEST
|
||||
i40e_debug(hw, I40E_DEBUG_DIAG,
|
||||
"%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\n",
|
||||
__func__, reg, pat, val);
|
||||
#endif
|
||||
return I40E_ERR_DIAG_TEST_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
wr32(hw, reg, orig_val);
|
||||
val = rd32(hw, reg);
|
||||
if (val != orig_val) {
|
||||
#ifdef ETHTOOL_TEST
|
||||
i40e_debug(hw, I40E_DEBUG_DIAG,
|
||||
"%s: reg restore test failed - reg 0x%08x orig_val 0x%08x val 0x%08x\n",
|
||||
__func__, reg, orig_val, val);
|
||||
#endif
|
||||
return I40E_ERR_DIAG_TEST_FAILED;
|
||||
}
|
||||
|
||||
return I40E_SUCCESS;
|
||||
}
|
||||
|
||||
struct i40e_diag_reg_test_info i40e_reg_list[] = {
|
||||
/* offset mask elements stride */
|
||||
{I40E_QTX_CTL(0), 0x0000FFBF, 1, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
|
||||
{I40E_PFINT_ITR0(0), 0x00000FFF, 3, I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)},
|
||||
{I40E_PFINT_ITRN(0, 0), 0x00000FFF, 1, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
|
||||
{I40E_PFINT_ITRN(1, 0), 0x00000FFF, 1, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
|
||||
{I40E_PFINT_ITRN(2, 0), 0x00000FFF, 1, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
|
||||
{I40E_PFINT_STAT_CTL0, 0x0000000C, 1, 0},
|
||||
{I40E_PFINT_LNKLST0, 0x00001FFF, 1, 0},
|
||||
{I40E_PFINT_LNKLSTN(0), 0x000007FF, 1, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
|
||||
{I40E_QINT_TQCTL(0), 0x000000FF, 1, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)},
|
||||
{I40E_QINT_RQCTL(0), 0x000000FF, 1, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)},
|
||||
{I40E_PFINT_ICR0_ENA, 0xF7F20000, 1, 0},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_diag_reg_test
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Perform registers diagnostic test
|
||||
**/
|
||||
i40e_status i40e_diag_reg_test(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code = I40E_SUCCESS;
|
||||
u32 reg, mask;
|
||||
u32 i, j;
|
||||
|
||||
for (i = 0; i40e_reg_list[i].offset != 0 &&
|
||||
ret_code == I40E_SUCCESS; i++) {
|
||||
|
||||
/* set actual reg range for dynamically allocated resources */
|
||||
if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&
|
||||
hw->func_caps.num_tx_qp != 0)
|
||||
i40e_reg_list[i].elements = hw->func_caps.num_tx_qp;
|
||||
if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||
|
||||
i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||
|
||||
i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||
|
||||
i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||
|
||||
i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&
|
||||
hw->func_caps.num_msix_vectors != 0)
|
||||
i40e_reg_list[i].elements =
|
||||
hw->func_caps.num_msix_vectors - 1;
|
||||
|
||||
/* test register access */
|
||||
mask = i40e_reg_list[i].mask;
|
||||
for (j = 0; j < i40e_reg_list[i].elements &&
|
||||
ret_code == I40E_SUCCESS; j++) {
|
||||
reg = i40e_reg_list[i].offset
|
||||
+ (j * i40e_reg_list[i].stride);
|
||||
ret_code = i40e_diag_reg_pattern_test(hw, reg, mask);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_diag_eeprom_test
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Perform EEPROM diagnostic test
|
||||
**/
|
||||
i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code;
|
||||
u16 reg_val;
|
||||
|
||||
/* read NVM control word and if NVM valid, validate EEPROM checksum*/
|
||||
ret_code = i40e_read_nvm_word(hw, I40E_SR_NVM_CONTROL_WORD, ®_val);
|
||||
if ((ret_code == I40E_SUCCESS) &&
|
||||
((reg_val & I40E_SR_CONTROL_WORD_1_MASK) ==
|
||||
BIT(I40E_SR_CONTROL_WORD_1_SHIFT)))
|
||||
return i40e_validate_nvm_checksum(hw, NULL);
|
||||
else
|
||||
return I40E_ERR_DIAG_TEST_FAILED;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_DIAG_H_
|
||||
#define _I40E_DIAG_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
||||
enum i40e_lb_mode {
|
||||
I40E_LB_MODE_NONE = 0x0,
|
||||
I40E_LB_MODE_PHY_LOCAL = I40E_AQ_LB_PHY_LOCAL,
|
||||
I40E_LB_MODE_PHY_REMOTE = I40E_AQ_LB_PHY_REMOTE,
|
||||
I40E_LB_MODE_MAC_LOCAL = I40E_AQ_LB_MAC_LOCAL,
|
||||
};
|
||||
|
||||
struct i40e_diag_reg_test_info {
|
||||
u32 offset; /* the base register */
|
||||
u32 mask; /* bits that can be tested */
|
||||
u32 elements; /* number of elements if array */
|
||||
u32 stride; /* bytes between each element */
|
||||
};
|
||||
|
||||
extern struct i40e_diag_reg_test_info i40e_reg_list[];
|
||||
|
||||
i40e_status i40e_diag_reg_test(struct i40e_hw *hw);
|
||||
i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw);
|
||||
|
||||
#endif /* _I40E_DIAG_H_ */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,124 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_FCOE_H_
|
||||
#define _I40E_FCOE_H_
|
||||
|
||||
/* FCoE HW context helper macros */
|
||||
#define I40E_DDP_CONTEXT_DESC(R, i) \
|
||||
(&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#define I40E_QUEUE_CONTEXT_DESC(R, i) \
|
||||
(&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#define I40E_FILTER_CONTEXT_DESC(R, i) \
|
||||
(&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
|
||||
|
||||
/* receive queue descriptor filter status for FCoE */
|
||||
#define I40E_RX_DESC_FLTSTAT_FCMASK 0x3
|
||||
#define I40E_RX_DESC_FLTSTAT_NOMTCH 0x0 /* no ddp context match */
|
||||
#define I40E_RX_DESC_FLTSTAT_NODDP 0x1 /* no ddp due to error */
|
||||
#define I40E_RX_DESC_FLTSTAT_DDP 0x2 /* DDPed payload, post header */
|
||||
#define I40E_RX_DESC_FLTSTAT_FCPRSP 0x3 /* FCP_RSP */
|
||||
|
||||
/* receive queue descriptor error codes for FCoE */
|
||||
#define I40E_RX_DESC_FCOE_ERROR_MASK \
|
||||
(I40E_RX_DESC_ERROR_L3L4E_PROT | \
|
||||
I40E_RX_DESC_ERROR_L3L4E_FC | \
|
||||
I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR | \
|
||||
I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
|
||||
|
||||
/* receive queue descriptor programming error */
|
||||
#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e) \
|
||||
(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
|
||||
|
||||
#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e) \
|
||||
(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
|
||||
|
||||
#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT \
|
||||
BIT(I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
|
||||
#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT \
|
||||
BIT(I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
|
||||
|
||||
#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e) \
|
||||
I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
|
||||
#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT \
|
||||
I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
|
||||
|
||||
/* FCoE DDP related definitions */
|
||||
#define I40E_FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
|
||||
#define I40E_FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */
|
||||
#define I40E_FCOE_DDP_BUFFCNT_MAX 512 /* 9 bits bufcnt */
|
||||
#define I40E_FCOE_DDP_PTR_ALIGN 16
|
||||
#define I40E_FCOE_DDP_PTR_MAX (I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
|
||||
#define I40E_FCOE_DDP_BUF_MIN 4096
|
||||
#define I40E_FCOE_DDP_MAX 2048
|
||||
#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT 8
|
||||
|
||||
/* supported netdev features for FCoE */
|
||||
#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
|
||||
NETIF_F_HW_VLAN_CTAG_TX | \
|
||||
NETIF_F_HW_VLAN_CTAG_RX | \
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER)
|
||||
|
||||
/* DDP context flags */
|
||||
enum i40e_fcoe_ddp_flags {
|
||||
__I40E_FCOE_DDP_NONE = 1,
|
||||
__I40E_FCOE_DDP_TARGET,
|
||||
__I40E_FCOE_DDP_INITALIZED,
|
||||
__I40E_FCOE_DDP_PROGRAMMED,
|
||||
__I40E_FCOE_DDP_DONE,
|
||||
__I40E_FCOE_DDP_ABORTED,
|
||||
__I40E_FCOE_DDP_UNMAPPED,
|
||||
};
|
||||
|
||||
/* DDP SW context struct */
|
||||
struct i40e_fcoe_ddp {
|
||||
int len;
|
||||
u16 xid;
|
||||
u16 firstoff;
|
||||
u16 lastsize;
|
||||
u16 list_len;
|
||||
u8 fcerr;
|
||||
u8 prerr;
|
||||
unsigned long flags;
|
||||
unsigned int sgc;
|
||||
struct scatterlist *sgl;
|
||||
dma_addr_t udp;
|
||||
u64 *udl;
|
||||
struct dma_pool *pool;
|
||||
|
||||
};
|
||||
|
||||
struct i40e_fcoe_ddp_pool {
|
||||
struct dma_pool *pool;
|
||||
};
|
||||
|
||||
struct i40e_fcoe {
|
||||
unsigned long mode;
|
||||
atomic_t refcnt;
|
||||
struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
|
||||
struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
|
||||
};
|
||||
|
||||
#endif /* _I40E_FCOE_H_ */
|
|
@ -0,0 +1,143 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_HELPER_H_
|
||||
#define _I40E_HELPER_H_
|
||||
|
||||
#include "i40e_alloc.h"
|
||||
|
||||
/**
|
||||
* i40e_allocate_dma_mem_d - OS specific memory alloc for shared code
|
||||
* @hw: pointer to the HW structure
|
||||
* @mem: ptr to mem struct to fill out
|
||||
* @size: size of memory requested
|
||||
* @alignment: what to align the allocation to
|
||||
**/
|
||||
inline int i40e_allocate_dma_mem_d(struct i40e_hw *hw,
|
||||
struct i40e_dma_mem *mem,
|
||||
__always_unused enum i40e_memory_type mtype,
|
||||
u64 size, u32 alignment)
|
||||
{
|
||||
struct i40e_pf *nf = (struct i40e_pf *)hw->back;
|
||||
|
||||
mem->size = ALIGN(size, alignment);
|
||||
mem->va = dma_zalloc_coherent(&nf->pdev->dev, mem->size,
|
||||
&mem->pa, GFP_KERNEL);
|
||||
if (!mem->va)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_free_dma_mem_d - OS specific memory free for shared code
|
||||
* @hw: pointer to the HW structure
|
||||
* @mem: ptr to mem struct to free
|
||||
**/
|
||||
inline int i40e_free_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem)
|
||||
{
|
||||
struct i40e_pf *nf = (struct i40e_pf *)hw->back;
|
||||
|
||||
dma_free_coherent(&nf->pdev->dev, mem->size, mem->va, mem->pa);
|
||||
mem->va = NULL;
|
||||
mem->pa = 0;
|
||||
mem->size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_allocate_virt_mem_d - OS specific memory alloc for shared code
|
||||
* @hw: pointer to the HW structure
|
||||
* @mem: ptr to mem struct to fill out
|
||||
* @size: size of memory requested
|
||||
**/
|
||||
inline int i40e_allocate_virt_mem_d(struct i40e_hw *hw,
|
||||
struct i40e_virt_mem *mem,
|
||||
u32 size)
|
||||
{
|
||||
mem->size = size;
|
||||
mem->va = kzalloc(size, GFP_KERNEL);
|
||||
|
||||
if (!mem->va)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_free_virt_mem_d - OS specific memory free for shared code
|
||||
* @hw: pointer to the HW structure
|
||||
* @mem: ptr to mem struct to free
|
||||
**/
|
||||
inline int i40e_free_virt_mem_d(struct i40e_hw *hw, struct i40e_virt_mem *mem)
|
||||
{
|
||||
/* it's ok to kfree a NULL pointer */
|
||||
kfree(mem->va);
|
||||
mem->va = NULL;
|
||||
mem->size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prototype */
|
||||
inline void i40e_destroy_spinlock_d(struct i40e_spinlock *sp);
|
||||
inline void i40e_acquire_spinlock_d(struct i40e_spinlock *sp);
|
||||
inline void i40e_release_spinlock_d(struct i40e_spinlock *sp);
|
||||
|
||||
/**
|
||||
* i40e_init_spinlock_d - OS specific spinlock init for shared code
|
||||
* @sp: pointer to a spinlock declared in driver space
|
||||
**/
|
||||
static inline void i40e_init_spinlock_d(struct i40e_spinlock *sp)
|
||||
{
|
||||
mutex_init((struct mutex *)sp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_acquire_spinlock_d - OS specific spinlock acquire for shared code
|
||||
* @sp: pointer to a spinlock declared in driver space
|
||||
**/
|
||||
inline void i40e_acquire_spinlock_d(struct i40e_spinlock *sp)
|
||||
{
|
||||
mutex_lock((struct mutex *)sp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_release_spinlock_d - OS specific spinlock release for shared code
|
||||
* @sp: pointer to a spinlock declared in driver space
|
||||
**/
|
||||
inline void i40e_release_spinlock_d(struct i40e_spinlock *sp)
|
||||
{
|
||||
mutex_unlock((struct mutex *)sp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_destroy_spinlock_d - OS specific spinlock destroy for shared code
|
||||
* @sp: pointer to a spinlock declared in driver space
|
||||
**/
|
||||
inline void i40e_destroy_spinlock_d(struct i40e_spinlock *sp)
|
||||
{
|
||||
mutex_destroy((struct mutex *)sp);
|
||||
}
|
||||
#endif /* _I40E_HELPER_H_ */
|
|
@ -0,0 +1,362 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_osdep.h"
|
||||
#include "i40e_register.h"
|
||||
#include "i40e_status.h"
|
||||
#include "i40e_alloc.h"
|
||||
#include "i40e_hmc.h"
|
||||
#ifndef I40E_NO_TYPE_HEADER
|
||||
#include "i40e_type.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* i40e_add_sd_table_entry - Adds a segment descriptor to the table
|
||||
* @hw: pointer to our hw struct
|
||||
* @hmc_info: pointer to the HMC configuration information struct
|
||||
* @sd_index: segment descriptor index to manipulate
|
||||
* @type: what type of segment descriptor we're manipulating
|
||||
* @direct_mode_sz: size to alloc in direct mode
|
||||
**/
|
||||
i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 sd_index,
|
||||
enum i40e_sd_entry_type type,
|
||||
u64 direct_mode_sz)
|
||||
{
|
||||
i40e_status ret_code = I40E_SUCCESS;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
enum i40e_memory_type mem_type;
|
||||
bool dma_mem_alloc_done = false;
|
||||
struct i40e_dma_mem mem;
|
||||
u64 alloc_len;
|
||||
|
||||
if (NULL == hmc_info->sd_table.sd_entry) {
|
||||
ret_code = I40E_ERR_BAD_PTR;
|
||||
hw_dbg(hw, "i40e_add_sd_table_entry: bad sd_entry\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (sd_index >= hmc_info->sd_table.sd_cnt) {
|
||||
ret_code = I40E_ERR_INVALID_SD_INDEX;
|
||||
hw_dbg(hw, "i40e_add_sd_table_entry: bad sd_index\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
|
||||
if (!sd_entry->valid) {
|
||||
if (I40E_SD_TYPE_PAGED == type) {
|
||||
mem_type = i40e_mem_pd;
|
||||
alloc_len = I40E_HMC_PAGED_BP_SIZE;
|
||||
} else {
|
||||
mem_type = i40e_mem_bp_jumbo;
|
||||
alloc_len = direct_mode_sz;
|
||||
}
|
||||
|
||||
/* allocate a 4K pd page or 2M backing page */
|
||||
ret_code = i40e_allocate_dma_mem(hw, &mem, mem_type, alloc_len,
|
||||
I40E_HMC_PD_BP_BUF_ALIGNMENT);
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
dma_mem_alloc_done = true;
|
||||
if (I40E_SD_TYPE_PAGED == type) {
|
||||
ret_code = i40e_allocate_virt_mem(hw,
|
||||
&sd_entry->u.pd_table.pd_entry_virt_mem,
|
||||
sizeof(struct i40e_hmc_pd_entry) * 512);
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
sd_entry->u.pd_table.pd_entry =
|
||||
(struct i40e_hmc_pd_entry *)
|
||||
sd_entry->u.pd_table.pd_entry_virt_mem.va;
|
||||
i40e_memcpy(&sd_entry->u.pd_table.pd_page_addr,
|
||||
&mem, sizeof(struct i40e_dma_mem),
|
||||
I40E_NONDMA_TO_NONDMA);
|
||||
} else {
|
||||
i40e_memcpy(&sd_entry->u.bp.addr,
|
||||
&mem, sizeof(struct i40e_dma_mem),
|
||||
I40E_NONDMA_TO_NONDMA);
|
||||
sd_entry->u.bp.sd_pd_index = sd_index;
|
||||
}
|
||||
/* initialize the sd entry */
|
||||
hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
|
||||
|
||||
/* increment the ref count */
|
||||
I40E_INC_SD_REFCNT(&hmc_info->sd_table);
|
||||
}
|
||||
/* Increment backing page reference count */
|
||||
if (I40E_SD_TYPE_DIRECT == sd_entry->entry_type)
|
||||
I40E_INC_BP_REFCNT(&sd_entry->u.bp);
|
||||
exit:
|
||||
if (I40E_SUCCESS != ret_code)
|
||||
if (dma_mem_alloc_done)
|
||||
i40e_free_dma_mem(hw, &mem);
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_add_pd_table_entry - Adds page descriptor to the specified table
|
||||
* @hw: pointer to our HW structure
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @pd_index: which page descriptor index to manipulate
|
||||
* @rsrc_pg: if not NULL, use preallocated page instead of allocating new one.
|
||||
*
|
||||
* This function:
|
||||
* 1. Initializes the pd entry
|
||||
* 2. Adds pd_entry in the pd_table
|
||||
* 3. Mark the entry valid in i40e_hmc_pd_entry structure
|
||||
* 4. Initializes the pd_entry's ref count to 1
|
||||
* assumptions:
|
||||
* 1. The memory for pd should be pinned down, physically contiguous and
|
||||
* aligned on 4K boundary and zeroed memory.
|
||||
* 2. It should be 4K in size.
|
||||
**/
|
||||
i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 pd_index,
|
||||
struct i40e_dma_mem *rsrc_pg)
|
||||
{
|
||||
i40e_status ret_code = I40E_SUCCESS;
|
||||
struct i40e_hmc_pd_table *pd_table;
|
||||
struct i40e_hmc_pd_entry *pd_entry;
|
||||
struct i40e_dma_mem mem;
|
||||
struct i40e_dma_mem *page = &mem;
|
||||
u32 sd_idx, rel_pd_idx;
|
||||
u64 *pd_addr;
|
||||
u64 page_desc;
|
||||
|
||||
if (pd_index / I40E_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt) {
|
||||
ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX;
|
||||
hw_dbg(hw, "i40e_add_pd_table_entry: bad pd_index\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* find corresponding sd */
|
||||
sd_idx = (pd_index / I40E_HMC_PD_CNT_IN_SD);
|
||||
if (I40E_SD_TYPE_PAGED !=
|
||||
hmc_info->sd_table.sd_entry[sd_idx].entry_type)
|
||||
goto exit;
|
||||
|
||||
rel_pd_idx = (pd_index % I40E_HMC_PD_CNT_IN_SD);
|
||||
pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
|
||||
pd_entry = &pd_table->pd_entry[rel_pd_idx];
|
||||
if (!pd_entry->valid) {
|
||||
if (rsrc_pg) {
|
||||
pd_entry->rsrc_pg = true;
|
||||
page = rsrc_pg;
|
||||
} else {
|
||||
/* allocate a 4K backing page */
|
||||
ret_code = i40e_allocate_dma_mem(hw, page, i40e_mem_bp,
|
||||
I40E_HMC_PAGED_BP_SIZE,
|
||||
I40E_HMC_PD_BP_BUF_ALIGNMENT);
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
pd_entry->rsrc_pg = false;
|
||||
}
|
||||
|
||||
i40e_memcpy(&pd_entry->bp.addr, page,
|
||||
sizeof(struct i40e_dma_mem), I40E_NONDMA_TO_NONDMA);
|
||||
pd_entry->bp.sd_pd_index = pd_index;
|
||||
pd_entry->bp.entry_type = I40E_SD_TYPE_PAGED;
|
||||
/* Set page address and valid bit */
|
||||
page_desc = page->pa | 0x1;
|
||||
|
||||
pd_addr = (u64 *)pd_table->pd_page_addr.va;
|
||||
pd_addr += rel_pd_idx;
|
||||
|
||||
/* Add the backing page physical address in the pd entry */
|
||||
i40e_memcpy(pd_addr, &page_desc, sizeof(u64),
|
||||
I40E_NONDMA_TO_DMA);
|
||||
|
||||
pd_entry->sd_index = sd_idx;
|
||||
pd_entry->valid = true;
|
||||
I40E_INC_PD_REFCNT(pd_table);
|
||||
}
|
||||
I40E_INC_BP_REFCNT(&pd_entry->bp);
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_remove_pd_bp - remove a backing page from a page descriptor
|
||||
* @hw: pointer to our HW structure
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: the page index
|
||||
* @is_pf: distinguishes a VF from a PF
|
||||
*
|
||||
* This function:
|
||||
* 1. Marks the entry in pd tabe (for paged address mode) or in sd table
|
||||
* (for direct address mode) invalid.
|
||||
* 2. Write to register PMPDINV to invalidate the backing page in FV cache
|
||||
* 3. Decrement the ref count for the pd _entry
|
||||
* assumptions:
|
||||
* 1. Caller can deallocate the memory used by backing storage after this
|
||||
* function returns.
|
||||
**/
|
||||
i40e_status i40e_remove_pd_bp(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx)
|
||||
{
|
||||
i40e_status ret_code = I40E_SUCCESS;
|
||||
struct i40e_hmc_pd_entry *pd_entry;
|
||||
struct i40e_hmc_pd_table *pd_table;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
u32 sd_idx, rel_pd_idx;
|
||||
u64 *pd_addr;
|
||||
|
||||
/* calculate index */
|
||||
sd_idx = idx / I40E_HMC_PD_CNT_IN_SD;
|
||||
rel_pd_idx = idx % I40E_HMC_PD_CNT_IN_SD;
|
||||
if (sd_idx >= hmc_info->sd_table.sd_cnt) {
|
||||
ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX;
|
||||
hw_dbg(hw, "i40e_remove_pd_bp: bad idx\n");
|
||||
goto exit;
|
||||
}
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
|
||||
if (I40E_SD_TYPE_PAGED != sd_entry->entry_type) {
|
||||
ret_code = I40E_ERR_INVALID_SD_TYPE;
|
||||
hw_dbg(hw, "i40e_remove_pd_bp: wrong sd_entry type\n");
|
||||
goto exit;
|
||||
}
|
||||
/* get the entry and decrease its ref counter */
|
||||
pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
|
||||
pd_entry = &pd_table->pd_entry[rel_pd_idx];
|
||||
I40E_DEC_BP_REFCNT(&pd_entry->bp);
|
||||
if (pd_entry->bp.ref_cnt)
|
||||
goto exit;
|
||||
|
||||
/* mark the entry invalid */
|
||||
pd_entry->valid = false;
|
||||
I40E_DEC_PD_REFCNT(pd_table);
|
||||
pd_addr = (u64 *)pd_table->pd_page_addr.va;
|
||||
pd_addr += rel_pd_idx;
|
||||
i40e_memset(pd_addr, 0, sizeof(u64), I40E_DMA_MEM);
|
||||
I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, idx);
|
||||
|
||||
/* free memory here */
|
||||
if (!pd_entry->rsrc_pg)
|
||||
ret_code = i40e_free_dma_mem(hw, &(pd_entry->bp.addr));
|
||||
if (I40E_SUCCESS != ret_code)
|
||||
goto exit;
|
||||
if (!pd_table->ref_cnt)
|
||||
i40e_free_virt_mem(hw, &pd_table->pd_entry_virt_mem);
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: the page index
|
||||
**/
|
||||
i40e_status i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx)
|
||||
{
|
||||
i40e_status ret_code = I40E_SUCCESS;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
/* get the entry and decrease its ref counter */
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
I40E_DEC_BP_REFCNT(&sd_entry->u.bp);
|
||||
if (sd_entry->u.bp.ref_cnt) {
|
||||
ret_code = I40E_ERR_NOT_READY;
|
||||
goto exit;
|
||||
}
|
||||
I40E_DEC_SD_REFCNT(&hmc_info->sd_table);
|
||||
|
||||
/* mark the entry invalid */
|
||||
sd_entry->valid = false;
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_remove_sd_bp_new - Removes a backing page from a segment descriptor
|
||||
* @hw: pointer to our hw struct
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: the page index
|
||||
* @is_pf: used to distinguish between VF and PF
|
||||
**/
|
||||
i40e_status i40e_remove_sd_bp_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf)
|
||||
{
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
if (!is_pf)
|
||||
return I40E_NOT_SUPPORTED;
|
||||
|
||||
/* get the entry and decrease its ref counter */
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_DIRECT);
|
||||
|
||||
return i40e_free_dma_mem(hw, &(sd_entry->u.bp.addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: segment descriptor index to find the relevant page descriptor
|
||||
**/
|
||||
i40e_status i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx)
|
||||
{
|
||||
i40e_status ret_code = I40E_SUCCESS;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
|
||||
if (sd_entry->u.pd_table.ref_cnt) {
|
||||
ret_code = I40E_ERR_NOT_READY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* mark the entry invalid */
|
||||
sd_entry->valid = false;
|
||||
|
||||
I40E_DEC_SD_REFCNT(&hmc_info->sd_table);
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_remove_pd_page_new - Removes a PD page from sd entry.
|
||||
* @hw: pointer to our hw struct
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: segment descriptor index to find the relevant page descriptor
|
||||
* @is_pf: used to distinguish between VF and PF
|
||||
**/
|
||||
i40e_status i40e_remove_pd_page_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf)
|
||||
{
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
if (!is_pf)
|
||||
return I40E_NOT_SUPPORTED;
|
||||
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_PAGED);
|
||||
|
||||
return i40e_free_dma_mem(hw, &(sd_entry->u.pd_table.pd_page_addr));
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_HMC_H_
|
||||
#define _I40E_HMC_H_
|
||||
|
||||
#define I40E_HMC_MAX_BP_COUNT 512
|
||||
|
||||
/* forward-declare the HW struct for the compiler */
|
||||
struct i40e_hw;
|
||||
|
||||
#define I40E_HMC_INFO_SIGNATURE 0x484D5347 /* HMSG */
|
||||
#define I40E_HMC_PD_CNT_IN_SD 512
|
||||
#define I40E_HMC_DIRECT_BP_SIZE 0x200000 /* 2M */
|
||||
#define I40E_HMC_PAGED_BP_SIZE 4096
|
||||
#define I40E_HMC_PD_BP_BUF_ALIGNMENT 4096
|
||||
#define I40E_FIRST_VF_FPM_ID 16
|
||||
|
||||
struct i40e_hmc_obj_info {
|
||||
u64 base; /* base addr in FPM */
|
||||
u32 max_cnt; /* max count available for this hmc func */
|
||||
u32 cnt; /* count of objects driver actually wants to create */
|
||||
u64 size; /* size in bytes of one object */
|
||||
};
|
||||
|
||||
enum i40e_sd_entry_type {
|
||||
I40E_SD_TYPE_INVALID = 0,
|
||||
I40E_SD_TYPE_PAGED = 1,
|
||||
I40E_SD_TYPE_DIRECT = 2
|
||||
};
|
||||
|
||||
struct i40e_hmc_bp {
|
||||
enum i40e_sd_entry_type entry_type;
|
||||
struct i40e_dma_mem addr; /* populate to be used by hw */
|
||||
u32 sd_pd_index;
|
||||
u32 ref_cnt;
|
||||
};
|
||||
|
||||
struct i40e_hmc_pd_entry {
|
||||
struct i40e_hmc_bp bp;
|
||||
u32 sd_index;
|
||||
bool rsrc_pg;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct i40e_hmc_pd_table {
|
||||
struct i40e_dma_mem pd_page_addr; /* populate to be used by hw */
|
||||
struct i40e_hmc_pd_entry *pd_entry; /* [512] for sw book keeping */
|
||||
struct i40e_virt_mem pd_entry_virt_mem; /* virt mem for pd_entry */
|
||||
|
||||
u32 ref_cnt;
|
||||
u32 sd_index;
|
||||
};
|
||||
|
||||
struct i40e_hmc_sd_entry {
|
||||
enum i40e_sd_entry_type entry_type;
|
||||
bool valid;
|
||||
|
||||
union {
|
||||
struct i40e_hmc_pd_table pd_table;
|
||||
struct i40e_hmc_bp bp;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct i40e_hmc_sd_table {
|
||||
struct i40e_virt_mem addr; /* used to track sd_entry allocations */
|
||||
u32 sd_cnt;
|
||||
u32 ref_cnt;
|
||||
struct i40e_hmc_sd_entry *sd_entry; /* (sd_cnt*512) entries max */
|
||||
};
|
||||
|
||||
struct i40e_hmc_info {
|
||||
u32 signature;
|
||||
/* equals to pci func num for PF and dynamically allocated for VFs */
|
||||
u8 hmc_fn_id;
|
||||
u16 first_sd_index; /* index of the first available SD */
|
||||
|
||||
/* hmc objects */
|
||||
struct i40e_hmc_obj_info *hmc_obj;
|
||||
struct i40e_virt_mem hmc_obj_virt_mem;
|
||||
struct i40e_hmc_sd_table sd_table;
|
||||
};
|
||||
|
||||
#define I40E_INC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt++)
|
||||
#define I40E_INC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt++)
|
||||
#define I40E_INC_BP_REFCNT(bp) ((bp)->ref_cnt++)
|
||||
|
||||
#define I40E_DEC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt--)
|
||||
#define I40E_DEC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt--)
|
||||
#define I40E_DEC_BP_REFCNT(bp) ((bp)->ref_cnt--)
|
||||
|
||||
/**
|
||||
* I40E_SET_PF_SD_ENTRY - marks the sd entry as valid in the hardware
|
||||
* @hw: pointer to our hw struct
|
||||
* @pa: pointer to physical address
|
||||
* @sd_index: segment descriptor index
|
||||
* @type: if sd entry is direct or paged
|
||||
**/
|
||||
#define I40E_SET_PF_SD_ENTRY(hw, pa, sd_index, type) \
|
||||
{ \
|
||||
u32 val1, val2, val3; \
|
||||
val1 = (u32)(upper_32_bits(pa)); \
|
||||
val2 = (u32)(pa) | (I40E_HMC_MAX_BP_COUNT << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
|
||||
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) | \
|
||||
BIT(I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT); \
|
||||
val3 = (sd_index) | BIT_ULL(I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
|
||||
wr32((hw), I40E_PFHMC_SDDATAHIGH, val1); \
|
||||
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
|
||||
wr32((hw), I40E_PFHMC_SDCMD, val3); \
|
||||
}
|
||||
|
||||
/**
|
||||
* I40E_CLEAR_PF_SD_ENTRY - marks the sd entry as invalid in the hardware
|
||||
* @hw: pointer to our hw struct
|
||||
* @sd_index: segment descriptor index
|
||||
* @type: if sd entry is direct or paged
|
||||
**/
|
||||
#define I40E_CLEAR_PF_SD_ENTRY(hw, sd_index, type) \
|
||||
{ \
|
||||
u32 val2, val3; \
|
||||
val2 = (I40E_HMC_MAX_BP_COUNT << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
|
||||
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT); \
|
||||
val3 = (sd_index) | BIT_ULL(I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
|
||||
wr32((hw), I40E_PFHMC_SDDATAHIGH, 0); \
|
||||
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
|
||||
wr32((hw), I40E_PFHMC_SDCMD, val3); \
|
||||
}
|
||||
|
||||
/**
|
||||
* I40E_INVALIDATE_PF_HMC_PD - Invalidates the pd cache in the hardware
|
||||
* @hw: pointer to our hw struct
|
||||
* @sd_idx: segment descriptor index
|
||||
* @pd_idx: page descriptor index
|
||||
**/
|
||||
#define I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, pd_idx) \
|
||||
wr32((hw), I40E_PFHMC_PDINV, \
|
||||
(((sd_idx) << I40E_PFHMC_PDINV_PMSDIDX_SHIFT) | \
|
||||
((pd_idx) << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)))
|
||||
|
||||
/**
|
||||
* I40E_FIND_SD_INDEX_LIMIT - finds segment descriptor index limit
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @type: type of HMC resources we're searching
|
||||
* @index: starting index for the object
|
||||
* @cnt: number of objects we're trying to create
|
||||
* @sd_idx: pointer to return index of the segment descriptor in question
|
||||
* @sd_limit: pointer to return the maximum number of segment descriptors
|
||||
*
|
||||
* This function calculates the segment descriptor index and index limit
|
||||
* for the resource defined by i40e_hmc_rsrc_type.
|
||||
**/
|
||||
#define I40E_FIND_SD_INDEX_LIMIT(hmc_info, type, index, cnt, sd_idx, sd_limit)\
|
||||
{ \
|
||||
u64 fpm_addr, fpm_limit; \
|
||||
fpm_addr = (hmc_info)->hmc_obj[(type)].base + \
|
||||
(hmc_info)->hmc_obj[(type)].size * (index); \
|
||||
fpm_limit = fpm_addr + (hmc_info)->hmc_obj[(type)].size * (cnt);\
|
||||
*(sd_idx) = (u32)(fpm_addr / I40E_HMC_DIRECT_BP_SIZE); \
|
||||
*(sd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_DIRECT_BP_SIZE); \
|
||||
/* add one more to the limit to correct our range */ \
|
||||
*(sd_limit) += 1; \
|
||||
}
|
||||
|
||||
/**
|
||||
* I40E_FIND_PD_INDEX_LIMIT - finds page descriptor index limit
|
||||
* @hmc_info: pointer to the HMC configuration information struct
|
||||
* @type: HMC resource type we're examining
|
||||
* @idx: starting index for the object
|
||||
* @cnt: number of objects we're trying to create
|
||||
* @pd_index: pointer to return page descriptor index
|
||||
* @pd_limit: pointer to return page descriptor index limit
|
||||
*
|
||||
* Calculates the page descriptor index and index limit for the resource
|
||||
* defined by i40e_hmc_rsrc_type.
|
||||
**/
|
||||
#define I40E_FIND_PD_INDEX_LIMIT(hmc_info, type, idx, cnt, pd_index, pd_limit)\
|
||||
{ \
|
||||
u64 fpm_adr, fpm_limit; \
|
||||
fpm_adr = (hmc_info)->hmc_obj[(type)].base + \
|
||||
(hmc_info)->hmc_obj[(type)].size * (idx); \
|
||||
fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt); \
|
||||
*(pd_index) = (u32)(fpm_adr / I40E_HMC_PAGED_BP_SIZE); \
|
||||
*(pd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_PAGED_BP_SIZE); \
|
||||
/* add one more to the limit to correct our range */ \
|
||||
*(pd_limit) += 1; \
|
||||
}
|
||||
i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 sd_index,
|
||||
enum i40e_sd_entry_type type,
|
||||
u64 direct_mode_sz);
|
||||
|
||||
i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 pd_index,
|
||||
struct i40e_dma_mem *rsrc_pg);
|
||||
i40e_status i40e_remove_pd_bp(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx);
|
||||
i40e_status i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx);
|
||||
i40e_status i40e_remove_sd_bp_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf);
|
||||
i40e_status i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx);
|
||||
i40e_status i40e_remove_pd_page_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf);
|
||||
|
||||
#endif /* _I40E_HMC_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,178 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_LAN_HMC_H_
|
||||
#define _I40E_LAN_HMC_H_
|
||||
|
||||
/* forward-declare the HW struct for the compiler */
|
||||
struct i40e_hw;
|
||||
|
||||
/* HMC element context information */
|
||||
|
||||
/* Rx queue context data
|
||||
*
|
||||
* The sizes of the variables may be larger than needed due to crossing byte
|
||||
* boundaries. If we do not have the width of the variable set to the correct
|
||||
* size then we could end up shifting bits off the top of the variable when the
|
||||
* variable is at the top of a byte and crosses over into the next byte.
|
||||
*/
|
||||
struct i40e_hmc_obj_rxq {
|
||||
u16 head;
|
||||
u16 cpuid; /* bigger than needed, see above for reason */
|
||||
u64 base;
|
||||
u16 qlen;
|
||||
#define I40E_RXQ_CTX_DBUFF_SHIFT 7
|
||||
u16 dbuff; /* bigger than needed, see above for reason */
|
||||
#define I40E_RXQ_CTX_HBUFF_SHIFT 6
|
||||
u16 hbuff; /* bigger than needed, see above for reason */
|
||||
u8 dtype;
|
||||
u8 dsize;
|
||||
u8 crcstrip;
|
||||
u8 fc_ena;
|
||||
u8 l2tsel;
|
||||
u8 hsplit_0;
|
||||
u8 hsplit_1;
|
||||
u8 showiv;
|
||||
u32 rxmax; /* bigger than needed, see above for reason */
|
||||
u8 tphrdesc_ena;
|
||||
u8 tphwdesc_ena;
|
||||
u8 tphdata_ena;
|
||||
u8 tphhead_ena;
|
||||
u16 lrxqthresh; /* bigger than needed, see above for reason */
|
||||
u8 prefena; /* NOTE: normally must be set to 1 at init */
|
||||
};
|
||||
|
||||
/* Tx queue context data
|
||||
*
|
||||
* The sizes of the variables may be larger than needed due to crossing byte
|
||||
* boundaries. If we do not have the width of the variable set to the correct
|
||||
* size then we could end up shifting bits off the top of the variable when the
|
||||
* variable is at the top of a byte and crosses over into the next byte.
|
||||
*/
|
||||
struct i40e_hmc_obj_txq {
|
||||
u16 head;
|
||||
u8 new_context;
|
||||
u64 base;
|
||||
u8 fc_ena;
|
||||
u8 timesync_ena;
|
||||
u8 fd_ena;
|
||||
u8 alt_vlan_ena;
|
||||
u16 thead_wb;
|
||||
u8 cpuid;
|
||||
u8 head_wb_ena;
|
||||
u16 qlen;
|
||||
u8 tphrdesc_ena;
|
||||
u8 tphrpacket_ena;
|
||||
u8 tphwdesc_ena;
|
||||
u64 head_wb_addr;
|
||||
u32 crc;
|
||||
u16 rdylist;
|
||||
u8 rdylist_act;
|
||||
};
|
||||
|
||||
/* for hsplit_0 field of Rx HMC context */
|
||||
enum i40e_hmc_obj_rx_hsplit_0 {
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_NO_SPLIT = 0,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_L2 = 1,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_IP = 2,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_TCP_UDP = 4,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_SCTP = 8,
|
||||
};
|
||||
|
||||
/* fcoe_cntx and fcoe_filt are for debugging purpose only */
|
||||
struct i40e_hmc_obj_fcoe_cntx {
|
||||
u32 rsv[32];
|
||||
};
|
||||
|
||||
struct i40e_hmc_obj_fcoe_filt {
|
||||
u32 rsv[8];
|
||||
};
|
||||
|
||||
/* Context sizes for LAN objects */
|
||||
enum i40e_hmc_lan_object_size {
|
||||
I40E_HMC_LAN_OBJ_SZ_8 = 0x3,
|
||||
I40E_HMC_LAN_OBJ_SZ_16 = 0x4,
|
||||
I40E_HMC_LAN_OBJ_SZ_32 = 0x5,
|
||||
I40E_HMC_LAN_OBJ_SZ_64 = 0x6,
|
||||
I40E_HMC_LAN_OBJ_SZ_128 = 0x7,
|
||||
I40E_HMC_LAN_OBJ_SZ_256 = 0x8,
|
||||
I40E_HMC_LAN_OBJ_SZ_512 = 0x9,
|
||||
};
|
||||
|
||||
#define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512
|
||||
#define I40E_HMC_OBJ_SIZE_TXQ 128
|
||||
#define I40E_HMC_OBJ_SIZE_RXQ 32
|
||||
#define I40E_HMC_OBJ_SIZE_FCOE_CNTX 64
|
||||
#define I40E_HMC_OBJ_SIZE_FCOE_FILT 64
|
||||
|
||||
enum i40e_hmc_lan_rsrc_type {
|
||||
I40E_HMC_LAN_FULL = 0,
|
||||
I40E_HMC_LAN_TX = 1,
|
||||
I40E_HMC_LAN_RX = 2,
|
||||
I40E_HMC_FCOE_CTX = 3,
|
||||
I40E_HMC_FCOE_FILT = 4,
|
||||
I40E_HMC_LAN_MAX = 5
|
||||
};
|
||||
|
||||
enum i40e_hmc_model {
|
||||
I40E_HMC_MODEL_DIRECT_PREFERRED = 0,
|
||||
I40E_HMC_MODEL_DIRECT_ONLY = 1,
|
||||
I40E_HMC_MODEL_PAGED_ONLY = 2,
|
||||
I40E_HMC_MODEL_UNKNOWN,
|
||||
};
|
||||
|
||||
struct i40e_hmc_lan_create_obj_info {
|
||||
struct i40e_hmc_info *hmc_info;
|
||||
u32 rsrc_type;
|
||||
u32 start_idx;
|
||||
u32 count;
|
||||
enum i40e_sd_entry_type entry_type;
|
||||
u64 direct_mode_sz;
|
||||
};
|
||||
|
||||
struct i40e_hmc_lan_delete_obj_info {
|
||||
struct i40e_hmc_info *hmc_info;
|
||||
u32 rsrc_type;
|
||||
u32 start_idx;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
i40e_status i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
|
||||
u32 rxq_num, u32 fcoe_cntx_num,
|
||||
u32 fcoe_filt_num);
|
||||
i40e_status i40e_configure_lan_hmc(struct i40e_hw *hw,
|
||||
enum i40e_hmc_model model);
|
||||
i40e_status i40e_shutdown_lan_hmc(struct i40e_hw *hw);
|
||||
|
||||
i40e_status i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue);
|
||||
i40e_status i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue,
|
||||
struct i40e_hmc_obj_txq *s);
|
||||
i40e_status i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue);
|
||||
i40e_status i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue,
|
||||
struct i40e_hmc_obj_rxq *s);
|
||||
|
||||
#endif /* _I40E_LAN_HMC_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
|
@ -0,0 +1,148 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_OSDEP_H_
|
||||
#define _I40E_OSDEP_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/highuid.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm-generic/int-ll64.h>
|
||||
|
||||
#ifndef readq
|
||||
static inline __u64 readq(const volatile void __iomem *addr)
|
||||
{
|
||||
const volatile u32 __iomem *p = addr;
|
||||
u32 low, high;
|
||||
|
||||
low = readl(p);
|
||||
high = readl(p + 1);
|
||||
|
||||
return low + ((u64)high << 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef writeq
|
||||
static inline void writeq(__u64 val, volatile void __iomem *addr)
|
||||
{
|
||||
writel(val, addr);
|
||||
writel(val >> 32, addr + 4);
|
||||
}
|
||||
#endif
|
||||
#include "kcompat.h"
|
||||
|
||||
/* File to be the magic between shared code and
|
||||
* actual OS primitives
|
||||
*/
|
||||
|
||||
#ifndef hw_dbg
|
||||
#define hw_dbg(h, s, ...) do { \
|
||||
pr_debug("i40e %02x:%02x.%x " s, \
|
||||
(h)->bus.bus_id, (h)->bus.device, \
|
||||
(h)->bus.func, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
|
||||
#define rd32(a, reg) readl((a)->hw_addr + (reg))
|
||||
|
||||
#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
|
||||
#define rd64(a, reg) readq((a)->hw_addr + (reg))
|
||||
#define i40e_flush(a) readl((a)->hw_addr + I40E_GLGEN_STAT)
|
||||
/* memory allocation tracking */
|
||||
struct i40e_dma_mem {
|
||||
void *va;
|
||||
dma_addr_t pa;
|
||||
u32 size;
|
||||
} __packed;
|
||||
|
||||
#define i40e_allocate_dma_mem(h, m, unused, s, a) \
|
||||
i40e_allocate_dma_mem_d(h, m, unused, s, a)
|
||||
|
||||
#define i40e_free_dma_mem(h, m) i40e_free_dma_mem_d(h, m)
|
||||
|
||||
struct i40e_virt_mem {
|
||||
void *va;
|
||||
u32 size;
|
||||
} __packed;
|
||||
|
||||
#define i40e_allocate_virt_mem(h, m, s) i40e_allocate_virt_mem_d(h, m, s)
|
||||
#define i40e_free_virt_mem(h, m) i40e_free_virt_mem_d(h, m)
|
||||
|
||||
#define i40e_debug(h, m, s, ...) \
|
||||
do { \
|
||||
if (((m) & (h)->debug_mask)) \
|
||||
pr_info("i40e %02x:%02x.%x " s, \
|
||||
(h)->bus.bus_id, (h)->bus.device, \
|
||||
(h)->bus.func, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* these things are all directly replaced with sed during the kernel build */
|
||||
#define INLINE inline
|
||||
|
||||
|
||||
#define CPU_TO_LE16(o) cpu_to_le16(o)
|
||||
#define CPU_TO_LE32(s) cpu_to_le32(s)
|
||||
#define CPU_TO_LE64(h) cpu_to_le64(h)
|
||||
#define LE16_TO_CPU(a) le16_to_cpu(a)
|
||||
#define LE32_TO_CPU(c) le32_to_cpu(c)
|
||||
#define LE64_TO_CPU(k) le64_to_cpu(k)
|
||||
|
||||
/* SW spinlock */
|
||||
struct i40e_spinlock {
|
||||
struct mutex spinlock;
|
||||
};
|
||||
|
||||
static inline void i40e_no_action(struct i40e_spinlock *sp)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
/* the locks are initialized in _probe and destroyed in _remove
|
||||
* so make sure NOT to implement init/destroy here, as to
|
||||
* avoid the i40e_init_adminq code trying to reinitialize
|
||||
* the persistent lock memory
|
||||
*/
|
||||
#define i40e_init_spinlock(_sp) i40e_no_action(_sp)
|
||||
#define i40e_acquire_spinlock(_sp) i40e_acquire_spinlock_d(_sp)
|
||||
#define i40e_release_spinlock(_sp) i40e_release_spinlock_d(_sp)
|
||||
#define i40e_destroy_spinlock(_sp) i40e_no_action(_sp)
|
||||
|
||||
#define I40E_HTONL(a) htonl(a)
|
||||
|
||||
#define i40e_memset(a, b, c, d) memset((a), (b), (c))
|
||||
#define i40e_memcpy(a, b, c, d) memcpy((a), (b), (c))
|
||||
|
||||
typedef enum i40e_status_code i40e_status;
|
||||
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
|
||||
#ifdef WITH_FCOE
|
||||
#define I40E_FCOE
|
||||
#endif
|
||||
#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
|
||||
#endif /* _I40E_OSDEP_H_ */
|
|
@ -0,0 +1,435 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_PROTOTYPE_H_
|
||||
#define _I40E_PROTOTYPE_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
#include "i40e_alloc.h"
|
||||
#include "i40e_virtchnl.h"
|
||||
|
||||
/* Prototypes for shared code functions that are not in
|
||||
* the standard function pointer structures. These are
|
||||
* mostly because they are needed even before the init
|
||||
* has happened and will assist in the early SW and FW
|
||||
* setup.
|
||||
*/
|
||||
|
||||
/* adminq functions */
|
||||
i40e_status i40e_init_adminq(struct i40e_hw *hw);
|
||||
i40e_status i40e_shutdown_adminq(struct i40e_hw *hw);
|
||||
void i40e_adminq_init_ring_data(struct i40e_hw *hw);
|
||||
i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
|
||||
struct i40e_arq_event_info *e,
|
||||
u16 *events_pending);
|
||||
i40e_status i40e_asq_send_command(struct i40e_hw *hw,
|
||||
struct i40e_aq_desc *desc,
|
||||
void *buff, /* can be NULL */
|
||||
u16 buff_size,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
|
||||
/* debug function for adminq */
|
||||
void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,
|
||||
void *desc, void *buffer, u16 buf_len);
|
||||
|
||||
void i40e_idle_aq(struct i40e_hw *hw);
|
||||
bool i40e_check_asq_alive(struct i40e_hw *hw);
|
||||
i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading);
|
||||
|
||||
i40e_status i40e_aq_get_rss_lut(struct i40e_hw *hw, u16 seid,
|
||||
bool pf_lut, u8 *lut, u16 lut_size);
|
||||
i40e_status i40e_aq_set_rss_lut(struct i40e_hw *hw, u16 seid,
|
||||
bool pf_lut, u8 *lut, u16 lut_size);
|
||||
i40e_status i40e_aq_get_rss_key(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_get_set_rss_key_data *key);
|
||||
i40e_status i40e_aq_set_rss_key(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_get_set_rss_key_data *key);
|
||||
const char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
|
||||
const char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err);
|
||||
|
||||
u32 i40e_led_get(struct i40e_hw *hw);
|
||||
void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink);
|
||||
i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
|
||||
u16 led_addr, u32 mode);
|
||||
i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
|
||||
u16 *val);
|
||||
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
|
||||
u32 time, u32 interval);
|
||||
|
||||
/* admin send queue commands */
|
||||
|
||||
i40e_status i40e_aq_get_firmware_version(struct i40e_hw *hw,
|
||||
u16 *fw_major_version, u16 *fw_minor_version,
|
||||
u32 *fw_build,
|
||||
u16 *api_major_version, u16 *api_minor_version,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
|
||||
u32 reg_addr, u64 reg_val,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_debug_read_register(struct i40e_hw *hw,
|
||||
u32 reg_addr, u64 *reg_val,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_clear_default_vsi(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
|
||||
bool qualified_modules, bool report_init,
|
||||
struct i40e_aq_get_phy_abilities_resp *abilities,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_phy_config(struct i40e_hw *hw,
|
||||
struct i40e_aq_set_phy_config *config,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
|
||||
bool atomic_reset);
|
||||
i40e_status i40e_aq_set_phy_int_mask(struct i40e_hw *hw, u16 mask,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
|
||||
bool enable_link, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
|
||||
bool enable_lse, struct i40e_link_status *link,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_local_advt_reg(struct i40e_hw *hw,
|
||||
u64 advt_reg,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_send_driver_version(struct i40e_hw *hw,
|
||||
struct i40e_driver_version *dv,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_vsi(struct i40e_hw *hw,
|
||||
struct i40e_vsi_context *vsi_ctx,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
|
||||
u16 vsi_id, bool set_filter,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
|
||||
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details,
|
||||
bool rx_only_promisc);
|
||||
i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw,
|
||||
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_full_promiscuous(struct i40e_hw *hw,
|
||||
u16 seid, bool set,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw,
|
||||
u16 seid, bool enable, u16 vid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
|
||||
u16 seid, bool enable, u16 vid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
|
||||
u16 seid, bool enable, u16 vid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
|
||||
u16 seid, bool enable,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
|
||||
struct i40e_vsi_context *vsi_ctx,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
|
||||
struct i40e_vsi_context *vsi_ctx,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,
|
||||
u16 downlink_seid, u8 enabled_tc,
|
||||
bool default_port, u16 *pveb_seid,
|
||||
bool enable_stats,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_veb_parameters(struct i40e_hw *hw,
|
||||
u16 veb_seid, u16 *switch_id, bool *floating,
|
||||
u16 *statistic_index, u16 *vebs_used,
|
||||
u16 *vebs_free,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_macvlan(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_aqc_add_macvlan_element_data *mv_list,
|
||||
u16 count, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_aqc_remove_macvlan_element_data *mv_list,
|
||||
u16 count, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
|
||||
u16 rule_type, u16 dest_vsi, u16 count, __le16 *mr_list,
|
||||
struct i40e_asq_cmd_details *cmd_details,
|
||||
u16 *rule_id, u16 *rules_used, u16 *rules_free);
|
||||
i40e_status i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
|
||||
u16 rule_type, u16 rule_id, u16 count, __le16 *mr_list,
|
||||
struct i40e_asq_cmd_details *cmd_details,
|
||||
u16 *rules_used, u16 *rules_free);
|
||||
|
||||
i40e_status i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid,
|
||||
u32 v_opcode, u32 v_retval, u8 *msg, u16 msglen,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_switch_config(struct i40e_hw *hw,
|
||||
struct i40e_aqc_get_switch_config_resp *buf,
|
||||
u16 buf_size, u16 *start_seid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_switch_config(struct i40e_hw *hw,
|
||||
u16 flags, u16 valid_flags,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_request_resource(struct i40e_hw *hw,
|
||||
enum i40e_aq_resources_ids resource,
|
||||
enum i40e_aq_resource_access_type access,
|
||||
u8 sdp_number, u64 *timeout,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_release_resource(struct i40e_hw *hw,
|
||||
enum i40e_aq_resources_ids resource,
|
||||
u8 sdp_number,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 length, void *data,
|
||||
bool last_command,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 length, bool last_command,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_read_nvm_config(struct i40e_hw *hw,
|
||||
u8 cmd_flags, u32 field_id, void *data,
|
||||
u16 buf_size, u16 *element_count,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_write_nvm_config(struct i40e_hw *hw,
|
||||
u8 cmd_flags, void *data, u16 buf_size,
|
||||
u16 element_count,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_oem_post_update(struct i40e_hw *hw,
|
||||
void *buff, u16 buff_size,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
|
||||
void *buff, u16 buff_size, u16 *data_size,
|
||||
enum i40e_admin_queue_opc list_type_opc,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 length, void *data,
|
||||
bool last_command,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type,
|
||||
u8 mib_type, void *buff, u16 buff_size,
|
||||
u16 *local_len, u16 *remote_len,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_lldp_mib(struct i40e_hw *hw,
|
||||
u8 mib_type, void *buff, u16 buff_size,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
|
||||
bool enable_update,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_cee_dcb_config(struct i40e_hw *hw,
|
||||
void *buff, u16 buff_size,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_start_stop_dcbx(struct i40e_hw *hw,
|
||||
bool start_agent,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw,
|
||||
u16 udp_port, u8 protocol_index,
|
||||
u8 *filter_index,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_switch_resource_alloc(struct i40e_hw *hw,
|
||||
u8 *num_entries,
|
||||
struct i40e_aqc_switch_resource_alloc_element_resp *buf,
|
||||
u16 count,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_delete_element(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_mac_address_write(struct i40e_hw *hw,
|
||||
u16 flags, u8 *mac_addr,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_vsi_bw_limit(struct i40e_hw *hw,
|
||||
u16 seid, u16 credit, u8 max_credit,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_dcb_updated(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_switch_comp_bw_limit(struct i40e_hw *hw,
|
||||
u16 seid, u16 credit, u8 max_bw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_vsi_tc_bw(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_configure_vsi_tc_bw_data *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_switch_comp_ets(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_configure_switching_comp_ets_data *ets_data,
|
||||
enum i40e_admin_queue_opc opcode,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_switch_comp_bw_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_configure_switching_comp_bw_config_data *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_vsi_bw_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_vsi_bw_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_vsi_ets_sla_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_vsi_ets_sla_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_switch_comp_ets_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_switching_comp_ets_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_port_ets_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_port_ets_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_switching_comp_bw_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_resume_port_tx(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw,
|
||||
struct i40e_lldp_variables *lldp_cfg);
|
||||
i40e_status i40e_aq_add_cloud_filters(struct i40e_hw *hw,
|
||||
u16 vsi,
|
||||
struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
|
||||
u8 filter_count);
|
||||
|
||||
i40e_status i40e_aq_remove_cloud_filters(struct i40e_hw *hw,
|
||||
u16 vsi,
|
||||
struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
|
||||
u8 filter_count);
|
||||
i40e_status i40e_aq_alternate_read(struct i40e_hw *hw,
|
||||
u32 reg_addr0, u32 *reg_val0,
|
||||
u32 reg_addr1, u32 *reg_val1);
|
||||
/* i40e_common */
|
||||
i40e_status i40e_init_shared_code(struct i40e_hw *hw);
|
||||
i40e_status i40e_pf_reset(struct i40e_hw *hw);
|
||||
void i40e_clear_hw(struct i40e_hw *hw);
|
||||
void i40e_clear_pxe_mode(struct i40e_hw *hw);
|
||||
i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up);
|
||||
i40e_status i40e_update_link_info(struct i40e_hw *hw);
|
||||
i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
|
||||
i40e_status i40e_read_bw_from_alt_ram(struct i40e_hw *hw,
|
||||
u32 *max_bw, u32 *min_bw, bool *min_valid, bool *max_valid);
|
||||
i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
|
||||
struct i40e_aqc_configure_partition_bw_data *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
|
||||
i40e_status i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num,
|
||||
u32 pba_num_size);
|
||||
void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable);
|
||||
#ifdef I40E_FCOE
|
||||
i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
|
||||
#endif
|
||||
/* prototype for functions used for NVM access */
|
||||
i40e_status i40e_init_nvm(struct i40e_hw *hw);
|
||||
i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
|
||||
enum i40e_aq_resource_access_type access);
|
||||
void i40e_release_nvm(struct i40e_hw *hw);
|
||||
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
|
||||
u16 *data);
|
||||
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
|
||||
u16 *words, u16 *data);
|
||||
i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module,
|
||||
u32 offset, u16 words, void *data,
|
||||
bool last_command);
|
||||
i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
|
||||
i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
|
||||
u16 *checksum);
|
||||
i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *);
|
||||
void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode);
|
||||
void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
|
||||
|
||||
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
|
||||
|
||||
static INLINE struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
|
||||
{
|
||||
return i40e_ptype_lookup[ptype];
|
||||
}
|
||||
|
||||
/* prototype for functions used for SW spinlocks */
|
||||
void i40e_init_spinlock(struct i40e_spinlock *sp);
|
||||
void i40e_acquire_spinlock(struct i40e_spinlock *sp);
|
||||
void i40e_release_spinlock(struct i40e_spinlock *sp);
|
||||
void i40e_destroy_spinlock(struct i40e_spinlock *sp);
|
||||
|
||||
/* i40e_common for VF drivers*/
|
||||
void i40e_vf_parse_hw_config(struct i40e_hw *hw,
|
||||
struct i40e_virtchnl_vf_resource *msg);
|
||||
i40e_status i40e_vf_reset(struct i40e_hw *hw);
|
||||
i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
|
||||
enum i40e_virtchnl_ops v_opcode,
|
||||
i40e_status v_retval,
|
||||
u8 *msg, u16 msglen,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_set_filter_control(struct i40e_hw *hw,
|
||||
struct i40e_filter_control_settings *settings);
|
||||
i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
|
||||
u8 *mac_addr, u16 ethtype, u16 flags,
|
||||
u16 vsi_seid, u16 queue, bool is_add,
|
||||
struct i40e_control_filter_stats *stats,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id,
|
||||
u8 table_id, u32 start_index, u16 buff_size,
|
||||
void *buff, u16 *ret_buff_size,
|
||||
u8 *ret_next_table, u32 *ret_next_index,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
|
||||
u16 vsi_seid);
|
||||
i40e_status i40e_aq_rx_ctl_read_register(struct i40e_hw *hw,
|
||||
u32 reg_addr, u32 *reg_val,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
u32 i40e_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr);
|
||||
i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
|
||||
u32 reg_addr, u32 reg_val,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
|
||||
i40e_status i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
|
||||
struct i40e_aqc_arp_proxy_data *proxy_config,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_ns_proxy_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_aqc_ns_proxy_data *ns_proxy_table_entry,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
|
||||
u8 filter_index,
|
||||
struct i40e_aqc_set_wol_filter_data *filter,
|
||||
bool set_filter, bool no_wol_tco,
|
||||
bool filter_valid, bool no_wol_tco_valid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_wake_event_reason(struct i40e_hw *hw,
|
||||
u16 *wake_reason,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_clear_all_wol_filters(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
|
||||
u16 reg, u8 phy_addr, u16 *value);
|
||||
i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
|
||||
u16 reg, u8 phy_addr, u16 value);
|
||||
i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
|
||||
u8 page, u16 reg, u8 phy_addr, u16 *value);
|
||||
i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
|
||||
u8 page, u16 reg, u8 phy_addr, u16 value);
|
||||
i40e_status i40e_read_phy_register(struct i40e_hw *hw,
|
||||
u8 page, u16 reg, u8 phy_addr, u16 *value);
|
||||
i40e_status i40e_write_phy_register(struct i40e_hw *hw,
|
||||
u8 page, u16 reg, u8 phy_addr, u16 value);
|
||||
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
|
||||
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
|
||||
u32 time, u32 interval);
|
||||
#endif /* _I40E_PROTOTYPE_H_ */
|
|
@ -0,0 +1,813 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* this lets the macros that return timespec64 or structs compile cleanly with
|
||||
* W=2
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Waggregate-return"
|
||||
#include "i40e.h"
|
||||
#ifdef HAVE_PTP_1588_CLOCK
|
||||
#include <linux/ptp_classify.h>
|
||||
|
||||
/* The XL710 timesync is very much like Intel's 82599 design when it comes to
|
||||
* the fundamental clock design. However, the clock operations are much simpler
|
||||
* in the XL710 because the device supports a full 64 bits of nanoseconds.
|
||||
* Because the field is so wide, we can forgo the cycle counter and just
|
||||
* operate with the nanosecond field directly without fear of overflow.
|
||||
*
|
||||
* Much like the 82599, the update period is dependent upon the link speed:
|
||||
* At 40Gb link or no link, the period is 1.6ns.
|
||||
* At 10Gb link, the period is multiplied by 2. (3.2ns)
|
||||
* At 1Gb link, the period is multiplied by 20. (32ns)
|
||||
* 1588 functionality is not supported at 100Mbps.
|
||||
*/
|
||||
#define I40E_PTP_40GB_INCVAL 0x0199999999ULL
|
||||
#define I40E_PTP_10GB_INCVAL 0x0333333333ULL
|
||||
#define I40E_PTP_1GB_INCVAL 0x2000000000ULL
|
||||
|
||||
#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 BIT(I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
|
||||
#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2 (2 << \
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
|
||||
|
||||
/**
|
||||
* i40e_ptp_read - Read the PHC time from the device
|
||||
* @pf: Board private structure
|
||||
* @ts: timespec structure to hold the current time value
|
||||
*
|
||||
* This function reads the PRTTSYN_TIME registers and stores them in a
|
||||
* timespec. However, since the registers are 64 bits of nanoseconds, we must
|
||||
* convert the result to a timespec before we can return.
|
||||
**/
|
||||
static void i40e_ptp_read(struct i40e_pf *pf, struct timespec64 *ts)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 hi, lo;
|
||||
u64 ns;
|
||||
|
||||
/* The timer latches on the lowest register read. */
|
||||
lo = rd32(hw, I40E_PRTTSYN_TIME_L);
|
||||
hi = rd32(hw, I40E_PRTTSYN_TIME_H);
|
||||
|
||||
ns = (((u64)hi) << 32) | lo;
|
||||
|
||||
*ts = ns_to_timespec64(ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_write - Write the PHC time to the device
|
||||
* @pf: Board private structure
|
||||
* @ts: timespec structure that holds the new time value
|
||||
*
|
||||
* This function writes the PRTTSYN_TIME registers with the user value. Since
|
||||
* we receive a timespec from the stack, we must convert that timespec into
|
||||
* nanoseconds before programming the registers.
|
||||
**/
|
||||
static void i40e_ptp_write(struct i40e_pf *pf, const struct timespec64 *ts)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u64 ns = timespec64_to_ns(ts);
|
||||
|
||||
/* The timer will not update until the high register is written, so
|
||||
* write the low register first.
|
||||
*/
|
||||
wr32(hw, I40E_PRTTSYN_TIME_L, (u32)ns);
|
||||
wr32(hw, I40E_PRTTSYN_TIME_H, (u32)(ns >> 32));
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_convert_to_hwtstamp - Convert device clock to system time
|
||||
* @hwtstamps: Timestamp structure to update
|
||||
* @timestamp: Timestamp from the hardware
|
||||
*
|
||||
* We need to convert the NIC clock value into a hwtstamp which can be used by
|
||||
* the upper level timestamping functions. Since the timestamp is simply a 64-
|
||||
* bit nanosecond value, we can call ns_to_ktime directly to handle this.
|
||||
**/
|
||||
static void i40e_ptp_convert_to_hwtstamp(struct skb_shared_hwtstamps *hwtstamps,
|
||||
u64 timestamp)
|
||||
{
|
||||
memset(hwtstamps, 0, sizeof(*hwtstamps));
|
||||
|
||||
hwtstamps->hwtstamp = ns_to_ktime(timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_adjfreq - Adjust the PHC frequency
|
||||
* @ptp: The PTP clock structure
|
||||
* @ppb: Parts per billion adjustment from the base
|
||||
*
|
||||
* Adjust the frequency of the PHC by the indicated parts per billion from the
|
||||
* base frequency.
|
||||
**/
|
||||
static int i40e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u64 adj, freq, diff;
|
||||
int neg_adj = 0;
|
||||
|
||||
if (ppb < 0) {
|
||||
neg_adj = 1;
|
||||
ppb = -ppb;
|
||||
}
|
||||
|
||||
smp_mb(); /* Force any pending update before accessing. */
|
||||
adj = ACCESS_ONCE(pf->ptp_base_adj);
|
||||
|
||||
freq = adj;
|
||||
freq *= ppb;
|
||||
diff = div_u64(freq, 1000000000ULL);
|
||||
|
||||
if (neg_adj)
|
||||
adj -= diff;
|
||||
else
|
||||
adj += diff;
|
||||
|
||||
wr32(hw, I40E_PRTTSYN_INC_L, (u32)adj);
|
||||
wr32(hw, I40E_PRTTSYN_INC_H, (u32)(adj >> 32));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_adjtime - Adjust the PHC time
|
||||
* @ptp: The PTP clock structure
|
||||
* @delta: Offset in nanoseconds to adjust the PHC time by
|
||||
*
|
||||
* Adjust the frequency of the PHC by the indicated parts per billion from the
|
||||
* base frequency.
|
||||
**/
|
||||
static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
struct timespec64 now;
|
||||
|
||||
mutex_lock(&pf->tmreg_lock);
|
||||
|
||||
i40e_ptp_read(pf, &now);
|
||||
timespec64_add_ns(&now, delta);
|
||||
i40e_ptp_write(pf, (const struct timespec64 *)&now);
|
||||
|
||||
mutex_unlock(&pf->tmreg_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_gettime64 - Get the time of the PHC
|
||||
* @ptp: The PTP clock structure
|
||||
* @ts: timespec64 structure to hold the current time value
|
||||
*
|
||||
* Read the device clock and return the correct value on ns, after converting it
|
||||
* into a timespec struct.
|
||||
**/
|
||||
static int i40e_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
|
||||
mutex_lock(&pf->tmreg_lock);
|
||||
i40e_ptp_read(pf, ts);
|
||||
mutex_unlock(&pf->tmreg_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_settime64 - Set the time of the PHC
|
||||
* @ptp: The PTP clock structure
|
||||
* @ts: timespec64 structure that holds the new time value
|
||||
*
|
||||
* Set the device clock to the user input value. The conversion from timespec
|
||||
* to ns happens in the write function.
|
||||
**/
|
||||
static int i40e_ptp_settime64(struct ptp_clock_info *ptp,
|
||||
const struct timespec64 *ts)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
|
||||
mutex_lock(&pf->tmreg_lock);
|
||||
i40e_ptp_write(pf, ts);
|
||||
mutex_unlock(&pf->tmreg_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_PTP_CLOCK_INFO_GETTIME64
|
||||
/**
|
||||
* i40e_ptp_gettime - Get the time of the PHC
|
||||
* @ptp: The PTP clock structure
|
||||
* @ts: timespec structure to hold the current time value
|
||||
*
|
||||
* Read the device clock and return the correct value on ns, after converting it
|
||||
* into a timespec struct.
|
||||
**/
|
||||
static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
|
||||
{
|
||||
struct timespec64 ts64;
|
||||
int err;
|
||||
|
||||
err = i40e_ptp_gettime64(ptp, &ts64);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*ts = timespec64_to_timespec(ts64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_settime - Set the time of the PHC
|
||||
* @ptp: The PTP clock structure
|
||||
* @ts: timespec structure that holds the new time value
|
||||
*
|
||||
* Set the device clock to the user input value. The conversion from timespec
|
||||
* to ns happens in the write function.
|
||||
**/
|
||||
static int i40e_ptp_settime(struct ptp_clock_info *ptp,
|
||||
const struct timespec *ts)
|
||||
{
|
||||
struct timespec64 ts64 = timespec_to_timespec64(*ts);
|
||||
|
||||
return i40e_ptp_settime64(ptp, &ts64);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* i40e_ptp_feature_enable - Enable/disable ancillary features of the PHC subsystem
|
||||
* @ptp: The PTP clock structure
|
||||
* @rq: The requested feature to change
|
||||
* @on: Enable/disable flag
|
||||
*
|
||||
* The XL710 does not support any of the ancillary features of the PHC
|
||||
* subsystem, so this function may just return.
|
||||
**/
|
||||
static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_update_latch_events - Read I40E_PRTTSYN_STAT_1 and latch events
|
||||
* @pf: the PF data structure
|
||||
*
|
||||
* This function reads I40E_PRTTSYN_STAT_1 and updates the corresponding timers
|
||||
* for noticed latch events. This allows the driver to keep track of the first
|
||||
* time a latch event was noticed which will be used to help clear out Rx
|
||||
* timestamps for packets that got dropped or lost.
|
||||
*
|
||||
* This function will return the current value of I40E_PRTTSYN_STAT_1 and is
|
||||
* expected to be called only while under the ptp_rx_lock.
|
||||
**/
|
||||
static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 prttsyn_stat, new_latch_events;
|
||||
int i;
|
||||
|
||||
prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
|
||||
new_latch_events = prttsyn_stat & ~pf->latch_event_flags;
|
||||
|
||||
/* Update the jiffies time for any newly latched timestamp. This
|
||||
* ensures that we store the time that we first discovered a timestamp
|
||||
* was latched by the hardware. The service task will later determine
|
||||
* if we should free the latch and drop that timestamp should too much
|
||||
* time pass. This flow ensures that we only update jiffies for new
|
||||
* events latched since the last time we checked, and not all events
|
||||
* currently latched, so that the service task accounting remains
|
||||
* accurate.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (new_latch_events & BIT(i))
|
||||
pf->latch_events[i] = jiffies;
|
||||
}
|
||||
|
||||
/* Finally, we store the current status of the Rx timestamp latches */
|
||||
pf->latch_event_flags = prttsyn_stat;
|
||||
|
||||
return prttsyn_stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
|
||||
* @vsi: The VSI with the rings relevant to 1588
|
||||
*
|
||||
* This watchdog task is scheduled to detect error case where hardware has
|
||||
* dropped an Rx packet that was timestamped when the ring is full. The
|
||||
* particular error is rare but leaves the device in a state unable to timestamp
|
||||
* any future packets.
|
||||
**/
|
||||
void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct i40e_pf *pf = vsi->back;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
unsigned int i, cleared = 0;
|
||||
|
||||
/* Since we cannot turn off the Rx timestamp logic if the device is
|
||||
* configured for Tx timestamping, we check if Rx timestamping is
|
||||
* configured. We don't want to spuriously warn about Rx timestamp
|
||||
* hangs if we don't care about the timestamps.
|
||||
*/
|
||||
if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&pf->ptp_rx_lock);
|
||||
|
||||
/* Update current latch times for Rx events */
|
||||
i40e_ptp_get_rx_events(pf);
|
||||
|
||||
/* Check all the currently latched Rx events and see whether they have
|
||||
* been latched for over a second. It is assumed that any timestamp
|
||||
* should have been cleared within this time, or else it was captured
|
||||
* for a dropped frame that the driver never received. Thus, we will
|
||||
* clear any timestamp that has been latched for over 1 second.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
if ((pf->latch_event_flags & BIT(i)) &&
|
||||
time_is_before_jiffies(pf->latch_events[i] + HZ)) {
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(i));
|
||||
pf->latch_event_flags &= ~BIT(i);
|
||||
cleared++;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&pf->ptp_rx_lock);
|
||||
|
||||
/* Log a warning if more than 2 timestamps got dropped in the same
|
||||
* check. We don't want to warn about all drops because it can occur
|
||||
* in normal scenarios such as PTP frames on multicast addresses we
|
||||
* aren't listening to. However, administrator should know if this is
|
||||
* the reason packets aren't receiving timestamps.
|
||||
*/
|
||||
if (cleared > 2)
|
||||
dev_dbg(&pf->pdev->dev,
|
||||
"Dropped %d missed RXTIME timestamp events\n",
|
||||
cleared);
|
||||
|
||||
/* Finally, update the rx_hwtstamp_cleared counter */
|
||||
pf->rx_hwtstamp_cleared += cleared;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* Read the value of the Tx timestamp from the registers, convert it into a
|
||||
* value consumable by the stack, and store that result into the shhwtstamps
|
||||
* struct before returning it up the stack.
|
||||
**/
|
||||
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
|
||||
{
|
||||
struct skb_shared_hwtstamps shhwtstamps;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 hi, lo;
|
||||
u64 ns;
|
||||
|
||||
if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_tx)
|
||||
return;
|
||||
|
||||
/* don't attempt to timestamp if we don't have an skb */
|
||||
if (!pf->ptp_tx_skb)
|
||||
return;
|
||||
|
||||
lo = rd32(hw, I40E_PRTTSYN_TXTIME_L);
|
||||
hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
|
||||
|
||||
ns = (((u64)hi) << 32) | lo;
|
||||
|
||||
i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns);
|
||||
skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
|
||||
dev_kfree_skb_any(pf->ptp_tx_skb);
|
||||
pf->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_rx_hwtstamp - Utility function which checks for an Rx timestamp
|
||||
* @pf: Board private structure
|
||||
* @skb: Particular skb to send timestamp with
|
||||
* @index: Index into the receive timestamp registers for the timestamp
|
||||
*
|
||||
* The XL710 receives a notification in the receive descriptor with an offset
|
||||
* into the set of RXTIME registers where the timestamp is for that skb. This
|
||||
* function goes and fetches the receive timestamp from that offset, if a valid
|
||||
* one exists. The RXTIME registers are in ns, so we must convert the result
|
||||
* first.
|
||||
**/
|
||||
void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index)
|
||||
{
|
||||
u32 prttsyn_stat, hi, lo;
|
||||
struct i40e_hw *hw;
|
||||
u64 ns;
|
||||
|
||||
/* Since we cannot turn off the Rx timestamp logic if the device is
|
||||
* doing Tx timestamping, check if Rx timestamping is configured.
|
||||
*/
|
||||
if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx)
|
||||
return;
|
||||
|
||||
hw = &pf->hw;
|
||||
|
||||
spin_lock_bh(&pf->ptp_rx_lock);
|
||||
|
||||
/* Get current Rx events and update latch times */
|
||||
prttsyn_stat = i40e_ptp_get_rx_events(pf);
|
||||
|
||||
/* TODO: Should we warn about missing Rx timestamp event? */
|
||||
if (!(prttsyn_stat & BIT(index))) {
|
||||
spin_unlock_bh(&pf->ptp_rx_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear the latched event since we're about to read its register */
|
||||
pf->latch_event_flags &= ~BIT(index);
|
||||
|
||||
lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index));
|
||||
hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index));
|
||||
|
||||
spin_unlock_bh(&pf->ptp_rx_lock);
|
||||
|
||||
ns = (((u64)hi) << 32) | lo;
|
||||
|
||||
i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_set_increment - Utility function to update clock increment rate
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* During a link change, the DMA frequency that drives the 1588 logic will
|
||||
* change. In order to keep the PRTTSYN_TIME registers in units of nanoseconds,
|
||||
* we must update the increment value per clock tick.
|
||||
**/
|
||||
void i40e_ptp_set_increment(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_link_status *hw_link_info;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u64 incval;
|
||||
|
||||
hw_link_info = &hw->phy.link_info;
|
||||
|
||||
i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
|
||||
|
||||
switch (hw_link_info->link_speed) {
|
||||
case I40E_LINK_SPEED_10GB:
|
||||
incval = I40E_PTP_10GB_INCVAL;
|
||||
break;
|
||||
case I40E_LINK_SPEED_1GB:
|
||||
incval = I40E_PTP_1GB_INCVAL;
|
||||
break;
|
||||
case I40E_LINK_SPEED_100MB:
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n");
|
||||
incval = 0;
|
||||
break;
|
||||
case I40E_LINK_SPEED_40GB:
|
||||
default:
|
||||
incval = I40E_PTP_40GB_INCVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write the new increment value into the increment register. The
|
||||
* hardware will not update the clock until both registers have been
|
||||
* written.
|
||||
*/
|
||||
wr32(hw, I40E_PRTTSYN_INC_L, (u32)incval);
|
||||
wr32(hw, I40E_PRTTSYN_INC_H, (u32)(incval >> 32));
|
||||
|
||||
/* Update the base adjustement value. */
|
||||
ACCESS_ONCE(pf->ptp_base_adj) = incval;
|
||||
smp_mb(); /* Force the above update. */
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_get_ts_config - ioctl interface to read the HW timestamping
|
||||
* @pf: Board private structure
|
||||
* @ifreq: ioctl data
|
||||
*
|
||||
* Obtain the current hardware timestamping settigs as requested. To do this,
|
||||
* keep a shadow copy of the timestamp settings rather than attempting to
|
||||
* deconstruct it from the registers.
|
||||
**/
|
||||
int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
|
||||
{
|
||||
struct hwtstamp_config *config = &pf->tstamp_config;
|
||||
|
||||
if (!(pf->flags & I40E_FLAG_PTP))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
|
||||
-EFAULT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_set_timestamp_mode - setup hardware for requested timestamp mode
|
||||
* @pf: Board private structure
|
||||
* @config: hwtstamp settings requested or saved
|
||||
*
|
||||
* Control hardware registers to enter the specific mode requested by the
|
||||
* user. Also used during reset path to ensure that timestamp settings are
|
||||
* maintained.
|
||||
*
|
||||
* Note: modifies config in place, and may update the requested mode to be
|
||||
* more broad if the specific filter is not directly supported.
|
||||
**/
|
||||
static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
|
||||
struct hwtstamp_config *config)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 tsyntype, regval;
|
||||
|
||||
/* Reserved for future extensions. */
|
||||
if (config->flags)
|
||||
return -EINVAL;
|
||||
|
||||
switch (config->tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
pf->ptp_tx = false;
|
||||
break;
|
||||
case HWTSTAMP_TX_ON:
|
||||
pf->ptp_tx = true;
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config->rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
pf->ptp_rx = false;
|
||||
/* We set the type to V1, but do not enable UDP packet
|
||||
* recognition. In this way, we should be as close to
|
||||
* disabling PTP Rx timestamps as possible since V1 packets
|
||||
* are always UDP, since L2 packets are a V2 feature.
|
||||
*/
|
||||
tsyntype = I40E_PRTTSYN_CTL1_TSYNTYPE_V1;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
|
||||
return -ERANGE;
|
||||
pf->ptp_rx = true;
|
||||
tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_V1 |
|
||||
I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
|
||||
return -ERANGE;
|
||||
/* fall through */
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
pf->ptp_rx = true;
|
||||
tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK |
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_V2;
|
||||
if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE) {
|
||||
tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
} else {
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
|
||||
}
|
||||
break;
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Clear out all 1588-related registers to clear and unlatch them. */
|
||||
spin_lock_bh(&pf->ptp_rx_lock);
|
||||
rd32(hw, I40E_PRTTSYN_STAT_0);
|
||||
rd32(hw, I40E_PRTTSYN_TXTIME_H);
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
|
||||
pf->latch_event_flags = 0;
|
||||
spin_unlock_bh(&pf->ptp_rx_lock);
|
||||
|
||||
/* Enable/disable the Tx timestamp interrupt based on user input. */
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL0);
|
||||
if (pf->ptp_tx)
|
||||
regval |= I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK;
|
||||
else
|
||||
regval &= ~I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK;
|
||||
wr32(hw, I40E_PRTTSYN_CTL0, regval);
|
||||
|
||||
regval = rd32(hw, I40E_PFINT_ICR0_ENA);
|
||||
if (pf->ptp_tx)
|
||||
regval |= I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
|
||||
else
|
||||
regval &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
|
||||
wr32(hw, I40E_PFINT_ICR0_ENA, regval);
|
||||
|
||||
/* Although there is no simple on/off switch for Rx, we "disable" Rx
|
||||
* timestamps by setting to V1 only mode and clear the UDP
|
||||
* recognition. This ought to disable all PTP Rx timestamps as V1
|
||||
* packets are always over UDP. Note that software is configured to
|
||||
* ignore Rx timestamps via the pf->ptp_rx flag.
|
||||
*/
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL1);
|
||||
/* clear everything but the enable bit */
|
||||
regval &= I40E_PRTTSYN_CTL1_TSYNENA_MASK;
|
||||
/* now enable bits for desired Rx timestamps */
|
||||
regval |= tsyntype;
|
||||
wr32(hw, I40E_PRTTSYN_CTL1, regval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
|
||||
* @pf: Board private structure
|
||||
* @ifreq: ioctl data
|
||||
*
|
||||
* Respond to the user filter requests and make the appropriate hardware
|
||||
* changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
|
||||
* logic, so keep track in software of whether to indicate these timestamps
|
||||
* or not.
|
||||
*
|
||||
* It is permissible to "upgrade" the user request to a broader filter, as long
|
||||
* as the user receives the timestamps they care about and the user is notified
|
||||
* the filter has been broadened.
|
||||
**/
|
||||
int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
|
||||
{
|
||||
struct hwtstamp_config config;
|
||||
int err;
|
||||
|
||||
if (!(pf->flags & I40E_FLAG_PTP))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
err = i40e_ptp_set_timestamp_mode(pf, &config);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* save these settings for future reference */
|
||||
pf->tstamp_config = config;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
|
||||
-EFAULT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_create_clock - Create PTP clock device for userspace
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* This function creates a new PTP clock device. It only creates one if we
|
||||
* don't already have one, so it is safe to call. Will return error if it
|
||||
* can't create one, but success if we already have a device. Should be used
|
||||
* by i40e_ptp_init to create clock initially, and prevent global resets from
|
||||
* creating new clock devices.
|
||||
**/
|
||||
static long i40e_ptp_create_clock(struct i40e_pf *pf)
|
||||
{
|
||||
/* no need to create a clock device if we already have one */
|
||||
if (!IS_ERR_OR_NULL(pf->ptp_clock))
|
||||
return 0;
|
||||
|
||||
strncpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name));
|
||||
pf->ptp_caps.owner = THIS_MODULE;
|
||||
pf->ptp_caps.max_adj = 999999999;
|
||||
pf->ptp_caps.n_ext_ts = 0;
|
||||
pf->ptp_caps.pps = 0;
|
||||
pf->ptp_caps.adjfreq = i40e_ptp_adjfreq;
|
||||
pf->ptp_caps.adjtime = i40e_ptp_adjtime;
|
||||
#ifdef HAVE_PTP_CLOCK_INFO_GETTIME64
|
||||
pf->ptp_caps.gettime64 = i40e_ptp_gettime64;
|
||||
pf->ptp_caps.settime64 = i40e_ptp_settime64;
|
||||
#else
|
||||
pf->ptp_caps.gettime = i40e_ptp_gettime;
|
||||
pf->ptp_caps.settime = i40e_ptp_settime;
|
||||
#endif
|
||||
pf->ptp_caps.enable = i40e_ptp_feature_enable;
|
||||
|
||||
/* Attempt to register the clock before enabling the hardware. */
|
||||
pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
|
||||
if (IS_ERR(pf->ptp_clock))
|
||||
return PTR_ERR(pf->ptp_clock);
|
||||
|
||||
/* clear the hwtstamp settings here during clock create, instead of
|
||||
* during regular init, so that we can maintain settings across a
|
||||
* reset or suspend.
|
||||
*/
|
||||
pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_init - Initialize the 1588 support after device probe or reset
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* This function sets device up for 1588 support. The first time it is run, it
|
||||
* will create a PHC clock device. It does not create a clock device if one
|
||||
* already exists. It also reconfigures the device after a reset.
|
||||
**/
|
||||
void i40e_ptp_init(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 pf_id;
|
||||
long err;
|
||||
|
||||
/* Only one PF is assigned to control 1588 logic per port. Do not
|
||||
* enable any support for PFs not assigned via PRTTSYN_CTL0.PF_ID
|
||||
*/
|
||||
pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
|
||||
I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
|
||||
if (hw->pf_id != pf_id) {
|
||||
pf->flags &= ~I40E_FLAG_PTP;
|
||||
dev_info(&pf->pdev->dev, "PTP not supported on this device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_init(&pf->tmreg_lock);
|
||||
spin_lock_init(&pf->ptp_rx_lock);
|
||||
|
||||
/* ensure we have a clock device */
|
||||
err = i40e_ptp_create_clock(pf);
|
||||
if (err) {
|
||||
pf->ptp_clock = NULL;
|
||||
dev_err(&pf->pdev->dev,
|
||||
"PTP clock register failed: %ld\n", err);
|
||||
} else {
|
||||
struct timespec64 ts;
|
||||
u32 regval;
|
||||
|
||||
if (pf->hw.debug_mask & I40E_DEBUG_LAN)
|
||||
dev_info(&pf->pdev->dev, "PHC enabled\n");
|
||||
pf->flags |= I40E_FLAG_PTP;
|
||||
|
||||
/* Ensure the clocks are running. */
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL0);
|
||||
regval |= I40E_PRTTSYN_CTL0_TSYNENA_MASK;
|
||||
wr32(hw, I40E_PRTTSYN_CTL0, regval);
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL1);
|
||||
regval |= I40E_PRTTSYN_CTL1_TSYNENA_MASK;
|
||||
wr32(hw, I40E_PRTTSYN_CTL1, regval);
|
||||
|
||||
/* Set the increment value per clock tick. */
|
||||
i40e_ptp_set_increment(pf);
|
||||
|
||||
/* reset timestamping mode */
|
||||
i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);
|
||||
|
||||
/* Set the clock value. */
|
||||
ts = ktime_to_timespec64(ktime_get_real());
|
||||
i40e_ptp_settime64(&pf->ptp_caps, &ts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_stop - Disable the driver/hardware support and unregister the PHC
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* This function handles the cleanup work required from the initialization by
|
||||
* clearing out the important information and unregistering the PHC.
|
||||
**/
|
||||
void i40e_ptp_stop(struct i40e_pf *pf)
|
||||
{
|
||||
pf->flags &= ~I40E_FLAG_PTP;
|
||||
pf->ptp_tx = false;
|
||||
pf->ptp_rx = false;
|
||||
|
||||
if (pf->ptp_tx_skb) {
|
||||
dev_kfree_skb_any(pf->ptp_tx_skb);
|
||||
pf->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
|
||||
}
|
||||
|
||||
if (pf->ptp_clock) {
|
||||
ptp_clock_unregister(pf->ptp_clock);
|
||||
pf->ptp_clock = NULL;
|
||||
dev_info(&pf->pdev->dev, "removed PHC from %s\n",
|
||||
pf->vsi[pf->lan_vsi]->netdev->name);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_PTP_1588_CLOCK */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,97 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_STATUS_H_
|
||||
#define _I40E_STATUS_H_
|
||||
|
||||
/* Error Codes */
|
||||
enum i40e_status_code {
|
||||
I40E_SUCCESS = 0,
|
||||
I40E_ERR_NVM = -1,
|
||||
I40E_ERR_NVM_CHECKSUM = -2,
|
||||
I40E_ERR_PHY = -3,
|
||||
I40E_ERR_CONFIG = -4,
|
||||
I40E_ERR_PARAM = -5,
|
||||
I40E_ERR_MAC_TYPE = -6,
|
||||
I40E_ERR_UNKNOWN_PHY = -7,
|
||||
I40E_ERR_LINK_SETUP = -8,
|
||||
I40E_ERR_ADAPTER_STOPPED = -9,
|
||||
I40E_ERR_INVALID_MAC_ADDR = -10,
|
||||
I40E_ERR_DEVICE_NOT_SUPPORTED = -11,
|
||||
I40E_ERR_MASTER_REQUESTS_PENDING = -12,
|
||||
I40E_ERR_INVALID_LINK_SETTINGS = -13,
|
||||
I40E_ERR_AUTONEG_NOT_COMPLETE = -14,
|
||||
I40E_ERR_RESET_FAILED = -15,
|
||||
I40E_ERR_SWFW_SYNC = -16,
|
||||
I40E_ERR_NO_AVAILABLE_VSI = -17,
|
||||
I40E_ERR_NO_MEMORY = -18,
|
||||
I40E_ERR_BAD_PTR = -19,
|
||||
I40E_ERR_RING_FULL = -20,
|
||||
I40E_ERR_INVALID_PD_ID = -21,
|
||||
I40E_ERR_INVALID_QP_ID = -22,
|
||||
I40E_ERR_INVALID_CQ_ID = -23,
|
||||
I40E_ERR_INVALID_CEQ_ID = -24,
|
||||
I40E_ERR_INVALID_AEQ_ID = -25,
|
||||
I40E_ERR_INVALID_SIZE = -26,
|
||||
I40E_ERR_INVALID_ARP_INDEX = -27,
|
||||
I40E_ERR_INVALID_FPM_FUNC_ID = -28,
|
||||
I40E_ERR_QP_INVALID_MSG_SIZE = -29,
|
||||
I40E_ERR_QP_TOOMANY_WRS_POSTED = -30,
|
||||
I40E_ERR_INVALID_FRAG_COUNT = -31,
|
||||
I40E_ERR_QUEUE_EMPTY = -32,
|
||||
I40E_ERR_INVALID_ALIGNMENT = -33,
|
||||
I40E_ERR_FLUSHED_QUEUE = -34,
|
||||
I40E_ERR_INVALID_PUSH_PAGE_INDEX = -35,
|
||||
I40E_ERR_INVALID_IMM_DATA_SIZE = -36,
|
||||
I40E_ERR_TIMEOUT = -37,
|
||||
I40E_ERR_OPCODE_MISMATCH = -38,
|
||||
I40E_ERR_CQP_COMPL_ERROR = -39,
|
||||
I40E_ERR_INVALID_VF_ID = -40,
|
||||
I40E_ERR_INVALID_HMCFN_ID = -41,
|
||||
I40E_ERR_BACKING_PAGE_ERROR = -42,
|
||||
I40E_ERR_NO_PBLCHUNKS_AVAILABLE = -43,
|
||||
I40E_ERR_INVALID_PBLE_INDEX = -44,
|
||||
I40E_ERR_INVALID_SD_INDEX = -45,
|
||||
I40E_ERR_INVALID_PAGE_DESC_INDEX = -46,
|
||||
I40E_ERR_INVALID_SD_TYPE = -47,
|
||||
I40E_ERR_MEMCPY_FAILED = -48,
|
||||
I40E_ERR_INVALID_HMC_OBJ_INDEX = -49,
|
||||
I40E_ERR_INVALID_HMC_OBJ_COUNT = -50,
|
||||
I40E_ERR_INVALID_SRQ_ARM_LIMIT = -51,
|
||||
I40E_ERR_SRQ_ENABLED = -52,
|
||||
I40E_ERR_ADMIN_QUEUE_ERROR = -53,
|
||||
I40E_ERR_ADMIN_QUEUE_TIMEOUT = -54,
|
||||
I40E_ERR_BUF_TOO_SHORT = -55,
|
||||
I40E_ERR_ADMIN_QUEUE_FULL = -56,
|
||||
I40E_ERR_ADMIN_QUEUE_NO_WORK = -57,
|
||||
I40E_ERR_BAD_IWARP_CQE = -58,
|
||||
I40E_ERR_NVM_BLANK_MODE = -59,
|
||||
I40E_ERR_NOT_IMPLEMENTED = -60,
|
||||
I40E_ERR_PE_DOORBELL_NOT_ENABLED = -61,
|
||||
I40E_ERR_DIAG_TEST_FAILED = -62,
|
||||
I40E_ERR_NOT_READY = -63,
|
||||
I40E_NOT_SUPPORTED = -64,
|
||||
I40E_ERR_FIRMWARE_API_VERSION = -65,
|
||||
};
|
||||
|
||||
#endif /* _I40E_STATUS_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,508 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_TXRX_H_
|
||||
#define _I40E_TXRX_H_
|
||||
|
||||
/* Interrupt Throttling and Rate Limiting Goodies */
|
||||
|
||||
#define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */
|
||||
#define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */
|
||||
#define I40E_ITR_100K 0x0005
|
||||
#define I40E_ITR_50K 0x000A
|
||||
#define I40E_ITR_20K 0x0019
|
||||
#define I40E_ITR_18K 0x001B
|
||||
#define I40E_ITR_8K 0x003E
|
||||
#define I40E_ITR_4K 0x007A
|
||||
#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */
|
||||
#define I40E_ITR_RX_DEF I40E_ITR_20K
|
||||
#define I40E_ITR_TX_DEF I40E_ITR_20K
|
||||
#define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
|
||||
#define I40E_MIN_INT_RATE 250 /* ~= 1000000 / (I40E_MAX_ITR * 2) */
|
||||
#define I40E_MAX_INT_RATE 500000 /* == 1000000 / (I40E_MIN_ITR * 2) */
|
||||
#define I40E_DEFAULT_IRQ_WORK 256
|
||||
#define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1)
|
||||
#define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC))
|
||||
#define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1)
|
||||
/* 0x40 is the enable bit for interrupt rate limiting, and must be set if
|
||||
* the value of the rate limit is non-zero
|
||||
*/
|
||||
#define INTRL_ENA BIT(6)
|
||||
#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2)
|
||||
/**
|
||||
* i40e_intrl_usec_to_reg - convert interrupt rate limit to register
|
||||
* @intrl: interrupt rate limit to convert
|
||||
*
|
||||
* This function converts a decimal interrupt rate limit to the appropriate
|
||||
* register format expected by the firmware when setting interrupt rate limit.
|
||||
*/
|
||||
static inline u16 i40e_intrl_usec_to_reg(int intrl)
|
||||
{
|
||||
if (intrl >> 2)
|
||||
return ((intrl >> 2) | INTRL_ENA);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#define I40E_INTRL_8K 125 /* 8000 ints/sec */
|
||||
#define I40E_INTRL_62K 16 /* 62500 ints/sec */
|
||||
#define I40E_INTRL_83K 12 /* 83333 ints/sec */
|
||||
|
||||
#define I40E_QUEUE_END_OF_LIST 0x7FF
|
||||
|
||||
/* this enum matches hardware bits and is meant to be used by DYN_CTLN
|
||||
* registers and QINT registers or more generally anywhere in the manual
|
||||
* mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any
|
||||
* register but instead is a special value meaning "don't update" ITR0/1/2.
|
||||
*/
|
||||
enum i40e_dyn_idx_t {
|
||||
I40E_IDX_ITR0 = 0,
|
||||
I40E_IDX_ITR1 = 1,
|
||||
I40E_IDX_ITR2 = 2,
|
||||
I40E_ITR_NONE = 3 /* ITR_NONE must not be used as an index */
|
||||
};
|
||||
|
||||
/* these are indexes into ITRN registers */
|
||||
#define I40E_RX_ITR I40E_IDX_ITR0
|
||||
#define I40E_TX_ITR I40E_IDX_ITR1
|
||||
#define I40E_PE_ITR I40E_IDX_ITR2
|
||||
|
||||
/* Supported RSS offloads */
|
||||
#define I40E_DEFAULT_RSS_HENA ( \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD))
|
||||
|
||||
#define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
|
||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
|
||||
|
||||
#define i40e_pf_get_default_rss_hena(pf) \
|
||||
(((pf)->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \
|
||||
I40E_DEFAULT_RSS_HENA_EXPANDED : I40E_DEFAULT_RSS_HENA)
|
||||
|
||||
/* Supported Rx Buffer Sizes (a multiple of 128) */
|
||||
#define I40E_RXBUFFER_256 256
|
||||
#define I40E_RXBUFFER_2048 2048
|
||||
#define I40E_RXBUFFER_3072 3072 /* For FCoE MTU of 2158 */
|
||||
#define I40E_RXBUFFER_4096 4096
|
||||
#define I40E_RXBUFFER_8192 8192
|
||||
#define I40E_MAX_RXBUFFER 9728 /* largest size for single descriptor */
|
||||
|
||||
/* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we
|
||||
* reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
|
||||
* this adds up to 512 bytes of extra data meaning the smallest allocation
|
||||
* we could have is 1K.
|
||||
* i.e. RXBUFFER_256 --> 960 byte skb (size-1024 slab)
|
||||
* i.e. RXBUFFER_512 --> 1216 byte skb (size-2048 slab)
|
||||
*/
|
||||
#define I40E_RX_HDR_SIZE I40E_RXBUFFER_256
|
||||
#define i40e_rx_desc i40e_32byte_rx_desc
|
||||
|
||||
/**
|
||||
* i40e_test_staterr - tests bits in Rx descriptor status and error fields
|
||||
* @rx_desc: pointer to receive descriptor (in le64 format)
|
||||
* @stat_err_bits: value to mask
|
||||
*
|
||||
* This function does some fast chicanery in order to return the
|
||||
* value of the mask which is really only used for boolean tests.
|
||||
* The status_error_len doesn't need to be shifted because it begins
|
||||
* at offset zero.
|
||||
*/
|
||||
static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,
|
||||
const u64 stat_err_bits)
|
||||
{
|
||||
return !!(rx_desc->wb.qword1.status_error_len &
|
||||
cpu_to_le64(stat_err_bits));
|
||||
}
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define I40E_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
#define I40E_RX_INCREMENT(r, i) \
|
||||
do { \
|
||||
(i)++; \
|
||||
if ((i) == (r)->count) \
|
||||
i = 0; \
|
||||
r->next_to_clean = i; \
|
||||
} while (0)
|
||||
|
||||
#define I40E_RX_NEXT_DESC(r, i, n) \
|
||||
do { \
|
||||
(i)++; \
|
||||
if ((i) == (r)->count) \
|
||||
i = 0; \
|
||||
(n) = I40E_RX_DESC((r), (i)); \
|
||||
} while (0)
|
||||
|
||||
#define I40E_RX_NEXT_DESC_PREFETCH(r, i, n) \
|
||||
do { \
|
||||
I40E_RX_NEXT_DESC((r), (i), (n)); \
|
||||
prefetch((n)); \
|
||||
} while (0)
|
||||
|
||||
#define I40E_MAX_BUFFER_TXD 8
|
||||
#define I40E_MIN_TX_LEN 17
|
||||
|
||||
/* The size limit for a transmit buffer in a descriptor is (16K - 1).
|
||||
* In order to align with the read requests we will align the value to
|
||||
* the nearest 4K which represents our maximum read request size.
|
||||
*/
|
||||
#define I40E_MAX_READ_REQ_SIZE 4096
|
||||
#define I40E_MAX_DATA_PER_TXD (16 * 1024 - 1)
|
||||
#define I40E_MAX_DATA_PER_TXD_ALIGNED \
|
||||
(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
|
||||
|
||||
/**
|
||||
* i40e_txd_use_count - estimate the number of descriptors needed for Tx
|
||||
* @size: transmit request size in bytes
|
||||
*
|
||||
* Due to hardware alignment restrictions (4K alignment), we need to
|
||||
* assume that we can have no more than 12K of data per descriptor, even
|
||||
* though each descriptor can take up to 16K - 1 bytes of aligned memory.
|
||||
* Thus, we need to divide by 12K. But division is slow! Instead,
|
||||
* we decompose the operation into shifts and one relatively cheap
|
||||
* multiply operation.
|
||||
*
|
||||
* To divide by 12K, we first divide by 4K, then divide by 3:
|
||||
* To divide by 4K, shift right by 12 bits
|
||||
* To divide by 3, multiply by 85, then divide by 256
|
||||
* (Divide by 256 is done by shifting right by 8 bits)
|
||||
* Finally, we add one to round up. Because 256 isn't an exact multiple of
|
||||
* 3, we'll underestimate near each multiple of 12K. This is actually more
|
||||
* accurate as we have 4K - 1 of wiggle room that we can fit into the last
|
||||
* segment. For our purposes this is accurate out to 1M which is orders of
|
||||
* magnitude greater than our largest possible GSO size.
|
||||
*
|
||||
* This would then be implemented as:
|
||||
* return (((size >> 12) * 85) >> 8) + 1;
|
||||
*
|
||||
* Since multiplication and division are commutative, we can reorder
|
||||
* operations into:
|
||||
* return ((size * 85) >> 20) + 1;
|
||||
*/
|
||||
static inline unsigned int i40e_txd_use_count(unsigned int size)
|
||||
{
|
||||
return ((size * 85) >> 20) + 1;
|
||||
}
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
#define I40E_MIN_DESC_PENDING 4
|
||||
|
||||
#define I40E_TX_FLAGS_HW_VLAN BIT(1)
|
||||
#define I40E_TX_FLAGS_SW_VLAN BIT(2)
|
||||
#define I40E_TX_FLAGS_TSO BIT(3)
|
||||
#define I40E_TX_FLAGS_IPV4 BIT(4)
|
||||
#define I40E_TX_FLAGS_IPV6 BIT(5)
|
||||
#define I40E_TX_FLAGS_FCCRC BIT(6)
|
||||
#define I40E_TX_FLAGS_FSO BIT(7)
|
||||
#ifdef HAVE_PTP_1588_CLOCK
|
||||
#define I40E_TX_FLAGS_TSYN BIT(8)
|
||||
#endif /* HAVE_PTP_1588_CLOCK */
|
||||
#define I40E_TX_FLAGS_FD_SB BIT(9)
|
||||
#define I40E_TX_FLAGS_TUNNEL BIT(10)
|
||||
#define I40E_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
|
||||
#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29
|
||||
#define I40E_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
struct i40e_tx_buffer {
|
||||
struct i40e_tx_desc *next_to_watch;
|
||||
union {
|
||||
struct sk_buff *skb;
|
||||
void *raw_buf;
|
||||
};
|
||||
unsigned int bytecount;
|
||||
unsigned short gso_segs;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct i40e_rx_buffer {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
unsigned int page_offset;
|
||||
};
|
||||
|
||||
struct i40e_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
};
|
||||
|
||||
struct i40e_tx_queue_stats {
|
||||
u64 restart_queue;
|
||||
u64 tx_busy;
|
||||
u64 tx_done_old;
|
||||
u64 tx_linearize;
|
||||
u64 tx_force_wb;
|
||||
u64 tx_lost_interrupt;
|
||||
};
|
||||
|
||||
struct i40e_rx_queue_stats {
|
||||
u64 non_eop_descs;
|
||||
u64 alloc_page_failed;
|
||||
u64 alloc_buff_failed;
|
||||
u64 page_reuse_count;
|
||||
u64 realloc_count;
|
||||
};
|
||||
|
||||
enum i40e_ring_state_t {
|
||||
__I40E_TX_FDIR_INIT_DONE,
|
||||
__I40E_TX_XPS_INIT_DONE,
|
||||
};
|
||||
|
||||
/* some useful defines for virtchannel interface, which
|
||||
* is the only remaining user of header split
|
||||
*/
|
||||
#define I40E_RX_DTYPE_NO_SPLIT 0
|
||||
#define I40E_RX_DTYPE_HEADER_SPLIT 1
|
||||
#define I40E_RX_DTYPE_SPLIT_ALWAYS 2
|
||||
#define I40E_RX_SPLIT_L2 0x1
|
||||
#define I40E_RX_SPLIT_IP 0x2
|
||||
#define I40E_RX_SPLIT_TCP_UDP 0x4
|
||||
#define I40E_RX_SPLIT_SCTP 0x8
|
||||
|
||||
/* struct that defines a descriptor ring, associated with a VSI */
|
||||
struct i40e_ring {
|
||||
struct i40e_ring *next; /* pointer to next ring in q_vector */
|
||||
void *desc; /* Descriptor ring memory */
|
||||
struct device *dev; /* Used for DMA mapping */
|
||||
struct net_device *netdev; /* netdev ring maps to */
|
||||
union {
|
||||
struct i40e_tx_buffer *tx_bi;
|
||||
struct i40e_rx_buffer *rx_bi;
|
||||
};
|
||||
unsigned long state;
|
||||
u16 queue_index; /* Queue number of ring */
|
||||
u8 dcb_tc; /* Traffic class of ring */
|
||||
u8 __iomem *tail;
|
||||
|
||||
/* high bit set means dynamic, use accessor routines to read/write.
|
||||
* hardware only supports 2us resolution for the ITR registers.
|
||||
* these values always store the USER setting, and must be converted
|
||||
* before programming to a register.
|
||||
*/
|
||||
u16 rx_itr_setting;
|
||||
u16 tx_itr_setting;
|
||||
|
||||
u16 count; /* Number of descriptors */
|
||||
u16 reg_idx; /* HW register index of the ring */
|
||||
u16 rx_buf_len;
|
||||
|
||||
/* used in interrupt processing */
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
u8 atr_sample_rate;
|
||||
u8 atr_count;
|
||||
|
||||
bool ring_active; /* is ring online or not */
|
||||
bool arm_wb; /* do something to arm write back */
|
||||
u8 packet_stride;
|
||||
|
||||
u16 flags;
|
||||
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
|
||||
|
||||
/* stats structs */
|
||||
struct i40e_queue_stats stats;
|
||||
#ifdef HAVE_NDO_GET_STATS64
|
||||
struct u64_stats_sync syncp;
|
||||
#endif
|
||||
union {
|
||||
struct i40e_tx_queue_stats tx_stats;
|
||||
struct i40e_rx_queue_stats rx_stats;
|
||||
};
|
||||
|
||||
unsigned int size; /* length of descriptor ring in bytes */
|
||||
dma_addr_t dma; /* physical address of ring */
|
||||
|
||||
struct i40e_vsi *vsi; /* Backreference to associated VSI */
|
||||
struct i40e_q_vector *q_vector; /* Backreference to associated vector */
|
||||
|
||||
struct rcu_head rcu; /* to avoid race on free */
|
||||
u16 next_to_alloc;
|
||||
struct sk_buff *skb; /* When i40e_clean_rx_ring_irq() must
|
||||
* return before it sees the EOP for
|
||||
* the current packet, we save that skb
|
||||
* here and resume receiving this
|
||||
* packet the next time
|
||||
* i40e_clean_rx_ring_irq() is called
|
||||
* for this ring.
|
||||
*/
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
enum i40e_latency_range {
|
||||
I40E_LOWEST_LATENCY = 0,
|
||||
I40E_LOW_LATENCY = 1,
|
||||
I40E_BULK_LATENCY = 2,
|
||||
I40E_ULTRA_LATENCY = 3,
|
||||
};
|
||||
|
||||
struct i40e_ring_container {
|
||||
/* array of pointers to rings */
|
||||
struct i40e_ring *ring;
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 count;
|
||||
enum i40e_latency_range latency_range;
|
||||
u16 itr;
|
||||
};
|
||||
|
||||
/* iterator for handling rings in ring container */
|
||||
#define i40e_for_each_ring(pos, head) \
|
||||
for (pos = (head).ring; pos != NULL; pos = pos->next)
|
||||
|
||||
bool i40e_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
|
||||
netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
|
||||
#if !defined(HAVE_NET_DEVICE_OPS) && defined(HAVE_NETDEV_SELECT_QUEUE)
|
||||
extern u16 i40e_lan_select_queue(struct net_device *netdev,
|
||||
struct sk_buff *skb);
|
||||
#endif
|
||||
void i40e_clean_tx_ring(struct i40e_ring *tx_ring);
|
||||
void i40e_clean_rx_ring(struct i40e_ring *rx_ring);
|
||||
int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring);
|
||||
int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring);
|
||||
void i40e_free_tx_resources(struct i40e_ring *tx_ring);
|
||||
void i40e_free_rx_resources(struct i40e_ring *rx_ring);
|
||||
int i40e_napi_poll(struct napi_struct *napi, int budget);
|
||||
#ifdef I40E_FCOE
|
||||
void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
|
||||
struct i40e_tx_buffer *first, u32 tx_flags,
|
||||
const u8 hdr_len, u32 td_cmd, u32 td_offset);
|
||||
int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
|
||||
struct i40e_ring *tx_ring, u32 *flags);
|
||||
#endif
|
||||
void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
|
||||
u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw);
|
||||
int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
|
||||
bool __i40e_chk_linearize(struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* i40e_get_head - Retrieve head from head writeback
|
||||
* @tx_ring: tx ring to fetch head of
|
||||
*
|
||||
* Returns value of Tx ring head based on value stored
|
||||
* in head write-back location
|
||||
**/
|
||||
static inline u32 i40e_get_head(struct i40e_ring *tx_ring)
|
||||
{
|
||||
void *head = (struct i40e_tx_desc *)tx_ring->desc + tx_ring->count;
|
||||
|
||||
return le32_to_cpu(*(volatile __le32 *)head);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_rx_is_fcoe - returns true if the rx packet type is FCoE
|
||||
* @ptype: the packet type field from rx descriptor write-back
|
||||
**/
|
||||
static inline bool i40e_rx_is_fcoe(u16 ptype)
|
||||
{
|
||||
return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) &&
|
||||
(ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_xmit_descriptor_count - calculate number of Tx descriptors needed
|
||||
* @skb: send buffer
|
||||
* @tx_ring: ring to send buffer on
|
||||
*
|
||||
* Returns number of data descriptors needed for this skb. Returns 0 to indicate
|
||||
* there is not enough descriptors available in this ring since we need at least
|
||||
* one descriptor.
|
||||
**/
|
||||
static inline int i40e_xmit_descriptor_count(struct sk_buff *skb)
|
||||
{
|
||||
const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
|
||||
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
int count = 0, size = skb_headlen(skb);
|
||||
|
||||
for (;;) {
|
||||
count += i40e_txd_use_count(size);
|
||||
|
||||
if (!nr_frags--)
|
||||
break;
|
||||
|
||||
size = skb_frag_size(frag++);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_maybe_stop_tx - 1st level check for Tx stop conditions
|
||||
* @tx_ring: the ring to be checked
|
||||
* @size: the size buffer we want to assure is available
|
||||
*
|
||||
* Returns 0 if stop is not needed
|
||||
**/
|
||||
static inline int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
|
||||
{
|
||||
if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
|
||||
return 0;
|
||||
return __i40e_maybe_stop_tx(tx_ring, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_chk_linearize - Check if there are more than 8 fragments per packet
|
||||
* @skb: send buffer
|
||||
* @count: number of buffers used
|
||||
*
|
||||
* Note: Our HW can't scatter-gather more than 8 fragments to build
|
||||
* a packet on the wire and so we need to figure out the cases where we
|
||||
* need to linearize the skb.
|
||||
**/
|
||||
static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
|
||||
{
|
||||
/* Both TSO and single send will work if count is less than 8 */
|
||||
if (likely(count < I40E_MAX_BUFFER_TXD))
|
||||
return false;
|
||||
|
||||
if (skb_is_gso(skb))
|
||||
return __i40e_chk_linearize(skb);
|
||||
|
||||
/* we can support up to 8 data buffers for a single send */
|
||||
return count != I40E_MAX_BUFFER_TXD;
|
||||
}
|
||||
|
||||
/**
|
||||
* txring_txq - Find the netdev Tx ring based on the i40e Tx ring
|
||||
* @ring: Tx ring to find the netdev equivalent of
|
||||
**/
|
||||
static inline struct netdev_queue *txring_txq(const struct i40e_ring *ring)
|
||||
{
|
||||
return netdev_get_tx_queue(ring->netdev, ring->queue_index);
|
||||
}
|
||||
#endif /* _I40E_TXRX_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,445 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_VIRTCHNL_H_
|
||||
#define _I40E_VIRTCHNL_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
||||
/* Description:
|
||||
* This header file describes the VF-PF communication protocol used
|
||||
* by the various i40e drivers.
|
||||
*
|
||||
* Admin queue buffer usage:
|
||||
* desc->opcode is always i40e_aqc_opc_send_msg_to_pf
|
||||
* flags, retval, datalen, and data addr are all used normally.
|
||||
* Firmware copies the cookie fields when sending messages between the PF and
|
||||
* VF, but uses all other fields internally. Due to this limitation, we
|
||||
* must send all messages as "indirect", i.e. using an external buffer.
|
||||
*
|
||||
* All the vsi indexes are relative to the VF. Each VF can have maximum of
|
||||
* three VSIs. All the queue indexes are relative to the VSI. Each VF can
|
||||
* have a maximum of sixteen queues for all of its VSIs.
|
||||
*
|
||||
* The PF is required to return a status code in v_retval for all messages
|
||||
* except RESET_VF, which does not require any response. The return value is of
|
||||
* i40e_status_code type, defined in the i40e_type.h.
|
||||
*
|
||||
* In general, VF driver initialization should roughly follow the order of these
|
||||
* opcodes. The VF driver must first validate the API version of the PF driver,
|
||||
* then request a reset, then get resources, then configure queues and
|
||||
* interrupts. After these operations are complete, the VF driver may start
|
||||
* its queues, optionally add MAC and VLAN filters, and process traffic.
|
||||
*/
|
||||
|
||||
/* Opcodes for VF-PF communication. These are placed in the v_opcode field
|
||||
* of the virtchnl_msg structure.
|
||||
*/
|
||||
enum i40e_virtchnl_ops {
|
||||
/* The PF sends status change events to VFs using
|
||||
* the I40E_VIRTCHNL_OP_EVENT opcode.
|
||||
* VFs send requests to the PF using the other ops.
|
||||
*/
|
||||
I40E_VIRTCHNL_OP_UNKNOWN = 0,
|
||||
I40E_VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
|
||||
I40E_VIRTCHNL_OP_RESET_VF = 2,
|
||||
I40E_VIRTCHNL_OP_GET_VF_RESOURCES = 3,
|
||||
I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE = 4,
|
||||
I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE = 5,
|
||||
I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6,
|
||||
I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP = 7,
|
||||
I40E_VIRTCHNL_OP_ENABLE_QUEUES = 8,
|
||||
I40E_VIRTCHNL_OP_DISABLE_QUEUES = 9,
|
||||
I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS = 10,
|
||||
I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS = 11,
|
||||
I40E_VIRTCHNL_OP_ADD_VLAN = 12,
|
||||
I40E_VIRTCHNL_OP_DEL_VLAN = 13,
|
||||
I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
|
||||
I40E_VIRTCHNL_OP_GET_STATS = 15,
|
||||
I40E_VIRTCHNL_OP_FCOE = 16,
|
||||
I40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
|
||||
I40E_VIRTCHNL_OP_IWARP = 20,
|
||||
I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21,
|
||||
I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22,
|
||||
I40E_VIRTCHNL_OP_CONFIG_RSS_KEY = 23,
|
||||
I40E_VIRTCHNL_OP_CONFIG_RSS_LUT = 24,
|
||||
I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,
|
||||
I40E_VIRTCHNL_OP_SET_RSS_HENA = 26,
|
||||
|
||||
};
|
||||
|
||||
/* Virtual channel message descriptor. This overlays the admin queue
|
||||
* descriptor. All other data is passed in external buffers.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_msg {
|
||||
u8 pad[8]; /* AQ flags/opcode/len/retval fields */
|
||||
enum i40e_virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
|
||||
i40e_status v_retval; /* ditto for desc->retval */
|
||||
u32 vfid; /* used by PF when sending to VF */
|
||||
};
|
||||
|
||||
/* Message descriptions and data structures.*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_VERSION
|
||||
* VF posts its version number to the PF. PF responds with its version number
|
||||
* in the same format, along with a return code.
|
||||
* Reply from PF has its major/minor versions also in param0 and param1.
|
||||
* If there is a major version mismatch, then the VF cannot operate.
|
||||
* If there is a minor version mismatch, then the VF can operate but should
|
||||
* add a warning to the system log.
|
||||
*
|
||||
* This enum element MUST always be specified as == 1, regardless of other
|
||||
* changes in the API. The PF must always respond to this message without
|
||||
* error regardless of version mismatch.
|
||||
*/
|
||||
#define I40E_VIRTCHNL_VERSION_MAJOR 1
|
||||
#define I40E_VIRTCHNL_VERSION_MINOR 1
|
||||
#define I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS 0
|
||||
|
||||
struct i40e_virtchnl_version_info {
|
||||
u32 major;
|
||||
u32 minor;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_RESET_VF
|
||||
* VF sends this request to PF with no parameters
|
||||
* PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
|
||||
* until reset completion is indicated. The admin queue must be reinitialized
|
||||
* after this operation.
|
||||
*
|
||||
* When reset is complete, PF must ensure that all queues in all VSIs associated
|
||||
* with the VF are stopped, all queue configurations in the HMC are set to 0,
|
||||
* and all MAC and VLAN filters (except the default MAC address) on all VSIs
|
||||
* are cleared.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_GET_VF_RESOURCES
|
||||
* Version 1.0 VF sends this request to PF with no parameters
|
||||
* Version 1.1 VF sends this request to PF with u32 bitmap of its capabilities
|
||||
* PF responds with an indirect message containing
|
||||
* i40e_virtchnl_vf_resource and one or more
|
||||
* i40e_virtchnl_vsi_resource structures.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_vsi_resource {
|
||||
u16 vsi_id;
|
||||
u16 num_queue_pairs;
|
||||
enum i40e_vsi_type vsi_type;
|
||||
u16 qset_handle;
|
||||
u8 default_mac_addr[ETH_ALEN];
|
||||
};
|
||||
/* VF offload flags */
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_IWARP 0x00000002
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 0x00040000
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00100000
|
||||
|
||||
#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
|
||||
I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
|
||||
I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
|
||||
|
||||
struct i40e_virtchnl_vf_resource {
|
||||
u16 num_vsis;
|
||||
u16 num_queue_pairs;
|
||||
u16 max_vectors;
|
||||
u16 max_mtu;
|
||||
|
||||
u32 vf_offload_flags;
|
||||
u32 rss_key_size;
|
||||
u32 rss_lut_size;
|
||||
|
||||
struct i40e_virtchnl_vsi_resource vsi_res[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE
|
||||
* VF sends this message to set up parameters for one TX queue.
|
||||
* External data buffer contains one instance of i40e_virtchnl_txq_info.
|
||||
* PF configures requested queue and returns a status code.
|
||||
*/
|
||||
|
||||
/* Tx queue config info */
|
||||
struct i40e_virtchnl_txq_info {
|
||||
u16 vsi_id;
|
||||
u16 queue_id;
|
||||
u16 ring_len; /* number of descriptors, multiple of 8 */
|
||||
u16 headwb_enabled;
|
||||
u64 dma_ring_addr;
|
||||
u64 dma_headwb_addr;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE
|
||||
* VF sends this message to set up parameters for one RX queue.
|
||||
* External data buffer contains one instance of i40e_virtchnl_rxq_info.
|
||||
* PF configures requested queue and returns a status code.
|
||||
*/
|
||||
|
||||
/* Rx queue config info */
|
||||
struct i40e_virtchnl_rxq_info {
|
||||
u16 vsi_id;
|
||||
u16 queue_id;
|
||||
u32 ring_len; /* number of descriptors, multiple of 32 */
|
||||
u16 hdr_size;
|
||||
u16 splithdr_enabled;
|
||||
u32 databuffer_size;
|
||||
u32 max_pkt_size;
|
||||
u64 dma_ring_addr;
|
||||
enum i40e_hmc_obj_rx_hsplit_0 rx_split_pos;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES
|
||||
* VF sends this message to set parameters for all active TX and RX queues
|
||||
* associated with the specified VSI.
|
||||
* PF configures queues and returns status.
|
||||
* If the number of queues specified is greater than the number of queues
|
||||
* associated with the VSI, an error is returned and no queues are configured.
|
||||
*/
|
||||
struct i40e_virtchnl_queue_pair_info {
|
||||
/* NOTE: vsi_id and queue_id should be identical for both queues. */
|
||||
struct i40e_virtchnl_txq_info txq;
|
||||
struct i40e_virtchnl_rxq_info rxq;
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_vsi_queue_config_info {
|
||||
u16 vsi_id;
|
||||
u16 num_queue_pairs;
|
||||
struct i40e_virtchnl_queue_pair_info qpair[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP
|
||||
* VF uses this message to map vectors to queues.
|
||||
* The rxq_map and txq_map fields are bitmaps used to indicate which queues
|
||||
* are to be associated with the specified vector.
|
||||
* The "other" causes are always mapped to vector 0.
|
||||
* PF configures interrupt mapping and returns status.
|
||||
*/
|
||||
struct i40e_virtchnl_vector_map {
|
||||
u16 vsi_id;
|
||||
u16 vector_id;
|
||||
u16 rxq_map;
|
||||
u16 txq_map;
|
||||
u16 rxitr_idx;
|
||||
u16 txitr_idx;
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_irq_map_info {
|
||||
u16 num_vectors;
|
||||
struct i40e_virtchnl_vector_map vecmap[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_ENABLE_QUEUES
|
||||
* I40E_VIRTCHNL_OP_DISABLE_QUEUES
|
||||
* VF sends these message to enable or disable TX/RX queue pairs.
|
||||
* The queues fields are bitmaps indicating which queues to act upon.
|
||||
* (Currently, we only support 16 queues per VF, but we make the field
|
||||
* u32 to allow for expansion.)
|
||||
* PF performs requested action and returns status.
|
||||
*/
|
||||
struct i40e_virtchnl_queue_select {
|
||||
u16 vsi_id;
|
||||
u16 pad;
|
||||
u32 rx_queues;
|
||||
u32 tx_queues;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS
|
||||
* VF sends this message in order to add one or more unicast or multicast
|
||||
* address filters for the specified VSI.
|
||||
* PF adds the filters and returns status.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS
|
||||
* VF sends this message in order to remove one or more unicast or multicast
|
||||
* filters for the specified VSI.
|
||||
* PF removes the filters and returns status.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_ether_addr {
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 pad[2];
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_ether_addr_list {
|
||||
u16 vsi_id;
|
||||
u16 num_elements;
|
||||
struct i40e_virtchnl_ether_addr list[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_ADD_VLAN
|
||||
* VF sends this message to add one or more VLAN tag filters for receives.
|
||||
* PF adds the filters and returns status.
|
||||
* If a port VLAN is configured by the PF, this operation will return an
|
||||
* error to the VF.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_DEL_VLAN
|
||||
* VF sends this message to remove one or more VLAN tag filters for receives.
|
||||
* PF removes the filters and returns status.
|
||||
* If a port VLAN is configured by the PF, this operation will return an
|
||||
* error to the VF.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_vlan_filter_list {
|
||||
u16 vsi_id;
|
||||
u16 num_elements;
|
||||
u16 vlan_id[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
|
||||
* VF sends VSI id and flags.
|
||||
* PF returns status code in retval.
|
||||
* Note: we assume that broadcast accept mode is always enabled.
|
||||
*/
|
||||
struct i40e_virtchnl_promisc_info {
|
||||
u16 vsi_id;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
#define I40E_FLAG_VF_UNICAST_PROMISC 0x00000001
|
||||
#define I40E_FLAG_VF_MULTICAST_PROMISC 0x00000002
|
||||
|
||||
/* I40E_VIRTCHNL_OP_GET_STATS
|
||||
* VF sends this message to request stats for the selected VSI. VF uses
|
||||
* the i40e_virtchnl_queue_select struct to specify the VSI. The queue_id
|
||||
* field is ignored by the PF.
|
||||
*
|
||||
* PF replies with struct i40e_eth_stats in an external buffer.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_RSS_KEY
|
||||
* I40E_VIRTCHNL_OP_CONFIG_RSS_LUT
|
||||
* VF sends these messages to configure RSS. Only supported if both PF
|
||||
* and VF drivers set the I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
|
||||
* configuration negotiation. If this is the case, then the rss fields in
|
||||
* the vf resource struct are valid.
|
||||
* Both the key and LUT are initialized to 0 by the PF, meaning that
|
||||
* RSS is effectively disabled until set up by the VF.
|
||||
*/
|
||||
struct i40e_virtchnl_rss_key {
|
||||
u16 vsi_id;
|
||||
u16 key_len;
|
||||
u8 key[1]; /* RSS hash key, packed bytes */
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_rss_lut {
|
||||
u16 vsi_id;
|
||||
u16 lut_entries;
|
||||
u8 lut[1]; /* RSS lookup table*/
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS
|
||||
* I40E_VIRTCHNL_OP_SET_RSS_HENA
|
||||
* VF sends these messages to get and set the hash filter enable bits for RSS.
|
||||
* By default, the PF sets these to all possible traffic types that the
|
||||
* hardware supports. The VF can query this value if it wants to change the
|
||||
* traffic types that are hashed by the hardware.
|
||||
* Traffic types are defined in the i40e_filter_pctype enum in i40e_type.h
|
||||
*/
|
||||
struct i40e_virtchnl_rss_hena {
|
||||
u64 hena;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_EVENT
|
||||
* PF sends this message to inform the VF driver of events that may affect it.
|
||||
* No direct response is expected from the VF, though it may generate other
|
||||
* messages in response to this one.
|
||||
*/
|
||||
enum i40e_virtchnl_event_codes {
|
||||
I40E_VIRTCHNL_EVENT_UNKNOWN = 0,
|
||||
I40E_VIRTCHNL_EVENT_LINK_CHANGE,
|
||||
I40E_VIRTCHNL_EVENT_RESET_IMPENDING,
|
||||
I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
|
||||
};
|
||||
#define I40E_PF_EVENT_SEVERITY_INFO 0
|
||||
#define I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM 255
|
||||
|
||||
struct i40e_virtchnl_pf_event {
|
||||
enum i40e_virtchnl_event_codes event;
|
||||
union {
|
||||
struct {
|
||||
enum i40e_aq_link_speed link_speed;
|
||||
bool link_status;
|
||||
} link_event;
|
||||
} event_data;
|
||||
|
||||
int severity;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP
|
||||
* VF uses this message to request PF to map IWARP vectors to IWARP queues.
|
||||
* The request for this originates from the VF IWARP driver through
|
||||
* a client interface between VF LAN and VF IWARP driver.
|
||||
* A vector could have an AEQ and CEQ attached to it although
|
||||
* there is a single AEQ per VF IWARP instance in which case
|
||||
* most vectors will have an INVALID_IDX for aeq and valid idx for ceq.
|
||||
* There will never be a case where there will be multiple CEQs attached
|
||||
* to a single vector.
|
||||
* PF configures interrupt mapping and returns status.
|
||||
*/
|
||||
|
||||
/* HW does not define a type value for AEQ; only for RX/TX and CEQ.
|
||||
* In order for us to keep the interface simple, SW will define a
|
||||
* unique type value for AEQ.
|
||||
*/
|
||||
#define I40E_QUEUE_TYPE_PE_AEQ 0x80
|
||||
#define I40E_QUEUE_INVALID_IDX 0xFFFF
|
||||
|
||||
struct i40e_virtchnl_iwarp_qv_info {
|
||||
u32 v_idx; /* msix_vector */
|
||||
u16 ceq_idx;
|
||||
u16 aeq_idx;
|
||||
u8 itr_idx;
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_iwarp_qvlist_info {
|
||||
u32 num_vectors;
|
||||
struct i40e_virtchnl_iwarp_qv_info qv_info[1];
|
||||
};
|
||||
|
||||
/* VF reset states - these are written into the RSTAT register:
|
||||
* I40E_VFGEN_RSTAT1 on the PF
|
||||
* I40E_VFGEN_RSTAT on the VF
|
||||
* When the PF initiates a reset, it writes 0
|
||||
* When the reset is complete, it writes 1
|
||||
* When the PF detects that the VF has recovered, it writes 2
|
||||
* VF checks this register periodically to determine if a reset has occurred,
|
||||
* then polls it to know when the reset is complete.
|
||||
* If either the PF or VF reads the register while the hardware
|
||||
* is in a reset state, it will return DEADBEEF, which, when masked
|
||||
* will result in 3.
|
||||
*/
|
||||
enum i40e_vfr_states {
|
||||
I40E_VFR_INPROGRESS = 0,
|
||||
I40E_VFR_COMPLETED,
|
||||
I40E_VFR_VFACTIVE,
|
||||
I40E_VFR_UNKNOWN,
|
||||
};
|
||||
|
||||
#endif /* _I40E_VIRTCHNL_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,171 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel(R) 40-10 Gigabit Ethernet Connection Network Driver
|
||||
* Copyright(c) 2013 - 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
* Contact Information:
|
||||
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _I40E_VIRTCHNL_PF_H_
|
||||
#define _I40E_VIRTCHNL_PF_H_
|
||||
|
||||
#include "i40e.h"
|
||||
|
||||
#define I40E_MAX_VLANID 4095
|
||||
|
||||
#define I40E_VIRTCHNL_SUPPORTED_QTYPES 2
|
||||
|
||||
#define I40E_DEFAULT_NUM_MDD_EVENTS_ALLOWED 3
|
||||
#define I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED 10
|
||||
|
||||
#define I40E_VLAN_PRIORITY_SHIFT 12
|
||||
#define I40E_VLAN_MASK 0xFFF
|
||||
#define I40E_PRIORITY_MASK 0x7000
|
||||
|
||||
#define VF_IS_V10(_v) (((_v)->vf_ver.major == 1) && ((_v)->vf_ver.minor == 0))
|
||||
#define VF_IS_V11(_v) (((_v)->vf_ver.major == 1) && ((_v)->vf_ver.minor == 1))
|
||||
|
||||
/* Various queue ctrls */
|
||||
enum i40e_queue_ctrl {
|
||||
I40E_QUEUE_CTRL_UNKNOWN = 0,
|
||||
I40E_QUEUE_CTRL_ENABLE,
|
||||
I40E_QUEUE_CTRL_ENABLECHECK,
|
||||
I40E_QUEUE_CTRL_DISABLE,
|
||||
I40E_QUEUE_CTRL_DISABLECHECK,
|
||||
I40E_QUEUE_CTRL_FASTDISABLE,
|
||||
I40E_QUEUE_CTRL_FASTDISABLECHECK,
|
||||
};
|
||||
|
||||
/* VF states */
|
||||
enum i40e_vf_states {
|
||||
I40E_VF_STAT_INIT = 0,
|
||||
I40E_VF_STAT_ACTIVE,
|
||||
I40E_VF_STAT_IWARPENA,
|
||||
I40E_VF_STAT_FCOEENA,
|
||||
I40E_VF_STAT_DISABLED,
|
||||
I40E_VF_STAT_MC_PROMISC,
|
||||
I40E_VF_STAT_UC_PROMISC,
|
||||
};
|
||||
|
||||
/* VF capabilities */
|
||||
enum i40e_vf_capabilities {
|
||||
I40E_VIRTCHNL_VF_CAP_PRIVILEGE = 0,
|
||||
I40E_VIRTCHNL_VF_CAP_L2,
|
||||
I40E_VIRTCHNL_VF_CAP_IWARP,
|
||||
#ifdef I40E_FCOE
|
||||
I40E_VIRTCHNL_VF_CAP_FCOE,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* VF information structure */
|
||||
struct i40e_vf {
|
||||
struct i40e_pf *pf;
|
||||
|
||||
/* VF id in the PF space */
|
||||
s16 vf_id;
|
||||
/* all VF vsis connect to the same parent */
|
||||
enum i40e_switch_element_types parent_type;
|
||||
struct i40e_virtchnl_version_info vf_ver;
|
||||
u32 driver_caps; /* reported by VF driver */
|
||||
|
||||
/* VF Port Extender (PE) stag if used */
|
||||
u16 stag;
|
||||
|
||||
struct i40e_virtchnl_ether_addr default_lan_addr;
|
||||
struct i40e_virtchnl_ether_addr default_fcoe_addr;
|
||||
u16 port_vlan_id;
|
||||
bool pf_set_mac; /* The VMM admin set the VF MAC address */
|
||||
bool trusted;
|
||||
|
||||
/* VSI indices - actual VSI pointers are maintained in the PF structure
|
||||
* When assigned, these will be non-zero, because VSI 0 is always
|
||||
* the main LAN VSI for the PF.
|
||||
*/
|
||||
u16 lan_vsi_idx; /* index into PF struct */
|
||||
u16 lan_vsi_id; /* ID as used by firmware */
|
||||
#ifdef I40E_FCOE
|
||||
u8 fcoe_vsi_index;
|
||||
u8 fcoe_vsi_id;
|
||||
#endif
|
||||
|
||||
u8 num_queue_pairs; /* num of qps assigned to VF vsis */
|
||||
u64 num_mdd_events; /* num of mdd events detected */
|
||||
/* num of continuous malformed or invalid msgs detected */
|
||||
u64 num_invalid_msgs;
|
||||
u64 num_valid_msgs; /* num of valid msgs detected */
|
||||
|
||||
unsigned long vf_caps; /* vf's adv. capabilities */
|
||||
unsigned long vf_states; /* vf's runtime states */
|
||||
unsigned int tx_rate; /* Tx bandwidth limit in Mbps */
|
||||
#ifdef HAVE_NDO_SET_VF_LINK_STATE
|
||||
bool link_forced;
|
||||
bool link_up; /* only valid if VF link is forced */
|
||||
#endif
|
||||
bool spoofchk;
|
||||
u16 num_mac;
|
||||
u16 num_vlan;
|
||||
|
||||
/* RDMA Client */
|
||||
struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info;
|
||||
};
|
||||
|
||||
void i40e_free_vfs(struct i40e_pf *pf);
|
||||
#if defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE)
|
||||
int i40e_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
|
||||
#endif
|
||||
int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
|
||||
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
|
||||
u32 v_retval, u8 *msg, u16 msglen);
|
||||
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
|
||||
void i40e_reset_vf(struct i40e_vf *vf, bool flr);
|
||||
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
|
||||
|
||||
/* VF configuration related iplink handlers */
|
||||
int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
|
||||
#ifdef IFLA_VF_VLAN_INFO_MAX
|
||||
int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
|
||||
u16 vlan_id, u8 qos, __be16 vlan_proto);
|
||||
#else
|
||||
int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
|
||||
int vf_id, u16 vlan_id, u8 qos);
|
||||
#endif
|
||||
#ifdef HAVE_NDO_SET_VF_MIN_MAX_TX_RATE
|
||||
int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
|
||||
int max_tx_rate);
|
||||
#else
|
||||
int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int tx_rate);
|
||||
#endif
|
||||
#ifdef HAVE_NDO_SET_VF_TRUST
|
||||
int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting);
|
||||
#endif
|
||||
int i40e_ndo_enable_vf(struct net_device *netdev, int vf_id, bool enable);
|
||||
#ifdef IFLA_VF_MAX
|
||||
int i40e_ndo_get_vf_config(struct net_device *netdev,
|
||||
int vf_id, struct ifla_vf_info *ivi);
|
||||
#ifdef HAVE_NDO_SET_VF_LINK_STATE
|
||||
int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link);
|
||||
#endif
|
||||
#ifdef HAVE_VF_SPOOFCHK_CONFIGURE
|
||||
int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void i40e_vc_notify_link_state(struct i40e_pf *pf);
|
||||
void i40e_vc_notify_reset(struct i40e_pf *pf);
|
||||
|
||||
#endif /* _I40E_VIRTCHNL_PF_H_ */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -32,8 +32,13 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "../kni/ethtool/ixgbe/ixgbe_type.h"
|
||||
#include "../kni/ethtool/igb/e1000_hw.h"
|
||||
#include <linux/hashtable.h>
|
||||
#include "i40e/i40e_type.h"
|
||||
#include "i40e/i40e_prototype.h"
|
||||
#include "i40e/i40e.h"
|
||||
#ifdef CONFIG_XEN_DOM0
|
||||
#include <xen/xen.h>
|
||||
#endif
|
||||
|
@ -44,10 +49,35 @@
|
|||
* struct to hold adapter-specific parameters
|
||||
* it currently supports Intel 1/10 Gbps adapters
|
||||
*/
|
||||
enum dev_type {IXGBE, IGB};
|
||||
enum dev_type {IXGBE, IGB, I40E};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* list of 1 Gbps cards */
|
||||
/* list of 1 Gbps controllers */
|
||||
static struct pci_device_id e1000_pci_tbl[] = {
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82540EM)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82545EM_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82545EM_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82546EB_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82546EB_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82546EB_QUAD_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82574LA)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82576)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES)},
|
||||
|
@ -56,20 +86,17 @@ static struct pci_device_id e1000_pci_tbl[] = {
|
|||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_DA4)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_OEM1)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_IT)},
|
||||
|
@ -79,18 +106,28 @@ static struct pci_device_id e1000_pci_tbl[] = {
|
|||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_FLASHLESS)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES_FLASHLESS)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_DA4)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_LM)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_V)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM2)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V2)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM3)},
|
||||
{PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V3)},
|
||||
/* required last entry */
|
||||
{0,}
|
||||
};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
|
||||
/* list of 10 Gbps controllers */
|
||||
static struct pci_device_id ixgbe_pci_tbl[] = {
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT)},
|
||||
|
@ -109,9 +146,11 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
|
|||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_SUBDEV_ID_82599_RNDC)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_SUBDEV_ID_82599_SFP)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_SUBDEV_ID_82599_560FLR)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_SUBDEV_ID_82599_ECNA_DP)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM)},
|
||||
|
@ -122,9 +161,48 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
|
|||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_1G_T)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550T)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550T1)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR_L)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII_L)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_10G_T)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_QSFP)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_QSFP_N)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_1G_T)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_1G_T_L)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KX4)},
|
||||
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR)},
|
||||
/* required last entry */
|
||||
{0, }
|
||||
};
|
||||
|
||||
/* list of 40 Gbps controllers */
|
||||
static struct pci_device_id i40e_pci_tbl[] = {
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_B)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_SFP28)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_B)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_C)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QEMU)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_A)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_B)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C)},
|
||||
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_XL710)},
|
||||
/* required last entry */
|
||||
{0, }
|
||||
};
|
||||
#define I40E_MAX_CSR_SPACE (4 * 1024 * 1024 - 64 * 1024)
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* net adapter private struct
|
||||
|
@ -136,6 +214,7 @@ struct net_adapter {
|
|||
union {
|
||||
struct ixgbe_hw _ixgbe_hw;
|
||||
struct e1000_hw _e1000_hw;
|
||||
struct i40e_hw _i40e_hw;
|
||||
} hw;
|
||||
u16 bd_number;
|
||||
bool netdev_registered;
|
||||
|
@ -154,8 +233,8 @@ struct stats_struct {
|
|||
uint8_t dev;
|
||||
};
|
||||
/* max qid */
|
||||
#define MAX_QID 16
|
||||
#define MAX_DEVICES 16
|
||||
#define MAX_QID 128
|
||||
#define MAX_DEVICES 128
|
||||
/* ioctl# */
|
||||
#define SEND_STATS 0
|
||||
/* major number */
|
||||
|
@ -406,6 +485,7 @@ retrieve_dev_addr(struct net_device *netdev, struct net_adapter *adapter)
|
|||
{
|
||||
struct ixgbe_hw *hw_i;
|
||||
struct e1000_hw *hw_e;
|
||||
struct i40e_hw *hw_i4;
|
||||
u32 rar_high;
|
||||
u32 rar_low;
|
||||
u16 i;
|
||||
|
@ -433,6 +513,22 @@ retrieve_dev_addr(struct net_device *netdev, struct net_adapter *adapter)
|
|||
for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
|
||||
netdev->dev_addr[i+4] = (u8)(rar_high >> (i*8));
|
||||
break;
|
||||
case I40E:
|
||||
hw_i4 = &adapter->hw._i40e_hw;
|
||||
(void) hw_i4;
|
||||
#if 0
|
||||
rar_high = E1000_READ_REG(hw_e, E1000_RAH(0));
|
||||
rar_low = E1000_READ_REG(hw_e, E1000_RAL(0));
|
||||
|
||||
for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
|
||||
netdev->dev_addr[i] = (u8)(rar_low >> (i*8));
|
||||
|
||||
for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
|
||||
netdev->dev_addr[i+4] = (u8)(rar_high >> (i*8));
|
||||
#else
|
||||
memcpy(netdev->dev_addr, hw_i4->mac.addr, ETH_ALEN);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -465,6 +561,15 @@ retrieve_dev_specs(const struct pci_device_id *id)
|
|||
|
||||
}
|
||||
|
||||
no_of_elements = sizeof(i40e_pci_tbl)/sizeof(struct pci_device_id);
|
||||
for (i = 0; i < no_of_elements; i++) {
|
||||
if (i40e_pci_tbl[i].vendor == id->vendor &&
|
||||
i40e_pci_tbl[i].device == id->device) {
|
||||
return I40E;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -341,6 +341,7 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
struct net_adapter *adapter = NULL;
|
||||
struct ixgbe_hw *hw_i = NULL;
|
||||
struct e1000_hw *hw_e = NULL;
|
||||
struct i40e_hw *hw_i4 = NULL;
|
||||
|
||||
udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL);
|
||||
if (!udev)
|
||||
|
@ -461,6 +462,15 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
goto fail_ioremap;
|
||||
}
|
||||
break;
|
||||
case I40E:
|
||||
hw_i4 = &adapter->hw._i40e_hw;
|
||||
hw_i4->back = adapter;
|
||||
|
||||
if (i40e_get_local_mac_addr(dev, id, hw_i4->mac.addr)) {
|
||||
err = -EIO;
|
||||
goto fail_ioremap;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
netdev_assign_netdev_ops(netdev);
|
||||
|
@ -534,6 +544,9 @@ igbuio_pci_remove(struct pci_dev *dev)
|
|||
case IGB:
|
||||
iounmap(udev->adapter->hw._e1000_hw.hw_addr);
|
||||
break;
|
||||
case I40E:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
free_netdev(netdev);
|
||||
|
||||
|
@ -570,7 +583,7 @@ igbuio_config_intr_mode(char *intr_str)
|
|||
}
|
||||
|
||||
static int
|
||||
update_stats(struct stats_struct __user *stats)
|
||||
update_stats(struct stats_struct *stats)
|
||||
{
|
||||
uint8_t qid = stats->qid;
|
||||
uint8_t device = stats->dev;
|
||||
|
@ -617,10 +630,17 @@ igb_net_ioctl(struct file *filp,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
struct stats_struct ss;
|
||||
|
||||
ret = copy_from_user(&ss,
|
||||
(struct stats_struct __user *)arg,
|
||||
sizeof(struct stats_struct));
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
||||
switch (cmd) {
|
||||
case SEND_STATS:
|
||||
ret = update_stats((struct stats_struct __user *) arg);
|
||||
ret = update_stats(&ss);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
|
@ -657,7 +677,7 @@ igbuio_pci_init_module(void)
|
|||
printk(KERN_ERR "register_chrdev failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return pci_register_driver(&igbuio_pci_driver);
|
||||
}
|
||||
|
|
@ -34,6 +34,102 @@
|
|||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82542 0x1000
|
||||
#define E1000_DEV_ID_82543GC_FIBER 0x1001
|
||||
#define E1000_DEV_ID_82543GC_COPPER 0x1004
|
||||
#define E1000_DEV_ID_82544EI_COPPER 0x1008
|
||||
#define E1000_DEV_ID_82544EI_FIBER 0x1009
|
||||
#define E1000_DEV_ID_82544GC_COPPER 0x100C
|
||||
#define E1000_DEV_ID_82544GC_LOM 0x100D
|
||||
#define E1000_DEV_ID_82540EM 0x100E
|
||||
#define E1000_DEV_ID_82540EM_LOM 0x1015
|
||||
#define E1000_DEV_ID_82540EP_LOM 0x1016
|
||||
#define E1000_DEV_ID_82540EP 0x1017
|
||||
#define E1000_DEV_ID_82540EP_LP 0x101E
|
||||
#define E1000_DEV_ID_82545EM_COPPER 0x100F
|
||||
#define E1000_DEV_ID_82545EM_FIBER 0x1011
|
||||
#define E1000_DEV_ID_82545GM_COPPER 0x1026
|
||||
#define E1000_DEV_ID_82545GM_FIBER 0x1027
|
||||
#define E1000_DEV_ID_82545GM_SERDES 0x1028
|
||||
#define E1000_DEV_ID_82546EB_COPPER 0x1010
|
||||
#define E1000_DEV_ID_82546EB_FIBER 0x1012
|
||||
#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
|
||||
#define E1000_DEV_ID_82546GB_COPPER 0x1079
|
||||
#define E1000_DEV_ID_82546GB_FIBER 0x107A
|
||||
#define E1000_DEV_ID_82546GB_SERDES 0x107B
|
||||
#define E1000_DEV_ID_82546GB_PCIE 0x108A
|
||||
#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
|
||||
#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
|
||||
#define E1000_DEV_ID_82541EI 0x1013
|
||||
#define E1000_DEV_ID_82541EI_MOBILE 0x1018
|
||||
#define E1000_DEV_ID_82541ER_LOM 0x1014
|
||||
#define E1000_DEV_ID_82541ER 0x1078
|
||||
#define E1000_DEV_ID_82541GI 0x1076
|
||||
#define E1000_DEV_ID_82541GI_LF 0x107C
|
||||
#define E1000_DEV_ID_82541GI_MOBILE 0x1077
|
||||
#define E1000_DEV_ID_82547EI 0x1019
|
||||
#define E1000_DEV_ID_82547EI_MOBILE 0x101A
|
||||
#define E1000_DEV_ID_82547GI 0x1075
|
||||
#define E1000_DEV_ID_82571EB_COPPER 0x105E
|
||||
#define E1000_DEV_ID_82571EB_FIBER 0x105F
|
||||
#define E1000_DEV_ID_82571EB_SERDES 0x1060
|
||||
#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
|
||||
#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA
|
||||
#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
|
||||
#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
|
||||
#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5
|
||||
#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC
|
||||
#define E1000_DEV_ID_82572EI_COPPER 0x107D
|
||||
#define E1000_DEV_ID_82572EI_FIBER 0x107E
|
||||
#define E1000_DEV_ID_82572EI_SERDES 0x107F
|
||||
#define E1000_DEV_ID_82572EI 0x10B9
|
||||
#define E1000_DEV_ID_82573E 0x108B
|
||||
#define E1000_DEV_ID_82573E_IAMT 0x108C
|
||||
#define E1000_DEV_ID_82573L 0x109A
|
||||
#define E1000_DEV_ID_82574L 0x10D3
|
||||
#define E1000_DEV_ID_82574LA 0x10F6
|
||||
#define E1000_DEV_ID_82583V 0x150C
|
||||
#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
|
||||
#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
|
||||
#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
|
||||
#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB
|
||||
#define E1000_DEV_ID_ICH8_82567V_3 0x1501
|
||||
#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049
|
||||
#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A
|
||||
#define E1000_DEV_ID_ICH8_IGP_C 0x104B
|
||||
#define E1000_DEV_ID_ICH8_IFE 0x104C
|
||||
#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4
|
||||
#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
|
||||
#define E1000_DEV_ID_ICH8_IGP_M 0x104D
|
||||
#define E1000_DEV_ID_ICH9_IGP_M 0x10BF
|
||||
#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5
|
||||
#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB
|
||||
#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD
|
||||
#define E1000_DEV_ID_ICH9_BM 0x10E5
|
||||
#define E1000_DEV_ID_ICH9_IGP_C 0x294C
|
||||
#define E1000_DEV_ID_ICH9_IFE 0x10C0
|
||||
#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3
|
||||
#define E1000_DEV_ID_ICH9_IFE_G 0x10C2
|
||||
#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC
|
||||
#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD
|
||||
#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE
|
||||
#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE
|
||||
#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF
|
||||
#define E1000_DEV_ID_ICH10_D_BM_V 0x1525
|
||||
#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA
|
||||
#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB
|
||||
#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF
|
||||
#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
|
||||
#define E1000_DEV_ID_PCH2_LV_LM 0x1502
|
||||
#define E1000_DEV_ID_PCH2_LV_V 0x1503
|
||||
#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A
|
||||
#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B
|
||||
#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A
|
||||
#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559
|
||||
#define E1000_DEV_ID_PCH_I218_LM2 0x15A0
|
||||
#define E1000_DEV_ID_PCH_I218_V2 0x15A1
|
||||
#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */
|
||||
#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */
|
||||
#define E1000_DEV_ID_82576 0x10C9
|
||||
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||
|
@ -42,6 +138,10 @@ struct e1000_hw;
|
|||
#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_82576_VF 0x10CA
|
||||
#define E1000_DEV_ID_82576_VF_HV 0x152D
|
||||
#define E1000_DEV_ID_I350_VF 0x1520
|
||||
#define E1000_DEV_ID_I350_VF_HV 0x152F
|
||||
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
|
||||
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
|
||||
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
|
||||
|
|
|
@ -55,6 +55,80 @@
|
|||
#define IXGBE_DEV_ID_82599_CX4 0x10F9
|
||||
#define IXGBE_DEV_ID_82599_SFP 0x10FB
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP_WOL0 0x1071
|
||||
#define IXGBE_SUBDEV_ID_82599_RNDC 0x1F72
|
||||
#define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0
|
||||
#define IXGBE_SUBDEV_ID_82599_ECNA_DP 0x0470
|
||||
#define IXGBE_SUBDEV_ID_82599_SP_560FLR 0x211B
|
||||
#define IXGBE_SUBDEV_ID_82599_LOM_SNAP6 0x2159
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP_1OCP 0x000D
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP_2OCP 0x0008
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM1 0x8976
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM2 0x06EE
|
||||
#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A
|
||||
#define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529
|
||||
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507
|
||||
#define IXGBE_DEV_ID_82599_SFP_SF2 0x154D
|
||||
#define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A
|
||||
#define IXGBE_DEV_ID_82599_QSFP_SF_QP 0x1558
|
||||
#define IXGBE_DEV_ID_82599EN_SFP 0x1557
|
||||
#define IXGBE_SUBDEV_ID_82599EN_SFP_OCP1 0x0001
|
||||
#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC
|
||||
#define IXGBE_DEV_ID_82599_T3_LOM 0x151C
|
||||
#define IXGBE_DEV_ID_82599_VF 0x10ED
|
||||
#define IXGBE_DEV_ID_82599_VF_HV 0x152E
|
||||
#define IXGBE_DEV_ID_82599_LS 0x154F
|
||||
#define IXGBE_DEV_ID_X540T 0x1528
|
||||
#define IXGBE_DEV_ID_X540_VF 0x1515
|
||||
#define IXGBE_DEV_ID_X540_VF_HV 0x1530
|
||||
#define IXGBE_DEV_ID_X540T1 0x1560
|
||||
#define IXGBE_DEV_ID_X550T 0x1563
|
||||
#define IXGBE_DEV_ID_X550T1 0x15D1
|
||||
/* Placeholder value, pending official value. */
|
||||
#define IXGBE_DEV_ID_X550EM_A_KR 0x15C2
|
||||
#define IXGBE_DEV_ID_X550EM_A_KR_L 0x15C3
|
||||
#define IXGBE_DEV_ID_X550EM_A_SFP_N 0x15C4
|
||||
#define IXGBE_DEV_ID_X550EM_A_SGMII 0x15C6
|
||||
#define IXGBE_DEV_ID_X550EM_A_SGMII_L 0x15C7
|
||||
#define IXGBE_DEV_ID_X550EM_A_10G_T 0x15C8
|
||||
#define IXGBE_DEV_ID_X550EM_A_QSFP 0x15CA
|
||||
#define IXGBE_DEV_ID_X550EM_A_QSFP_N 0x15CC
|
||||
#define IXGBE_DEV_ID_X550EM_A_SFP 0x15CE
|
||||
#define IXGBE_DEV_ID_X550EM_A_1G_T 0x15E4
|
||||
#define IXGBE_DEV_ID_X550EM_A_1G_T_L 0x15E5
|
||||
#define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA
|
||||
#define IXGBE_DEV_ID_X550EM_X_KR 0x15AB
|
||||
#define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC
|
||||
#define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD
|
||||
#define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE
|
||||
#define IXGBE_DEV_ID_X550_VF_HV 0x1564
|
||||
#define IXGBE_DEV_ID_X550_VF 0x1565
|
||||
#define IXGBE_DEV_ID_X550EM_A_VF 0x15C5
|
||||
#define IXGBE_DEV_ID_X550EM_A_VF_HV 0x15B4
|
||||
#define IXGBE_DEV_ID_X550EM_X_VF 0x15A8
|
||||
#define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9
|
||||
|
||||
#if 0
|
||||
#define IXGBE_DEV_ID_82598 0x10B6
|
||||
#define IXGBE_DEV_ID_82598_BX 0x1508
|
||||
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
|
||||
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
|
||||
#define IXGBE_DEV_ID_82598AT 0x10C8
|
||||
#define IXGBE_DEV_ID_82598AT2 0x150B
|
||||
#define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB
|
||||
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
|
||||
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
|
||||
#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
|
||||
#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1
|
||||
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
|
||||
#define IXGBE_DEV_ID_82599_KX4 0x10F7
|
||||
#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514
|
||||
#define IXGBE_DEV_ID_82599_KR 0x1517
|
||||
#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
|
||||
#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C
|
||||
#define IXGBE_DEV_ID_82599_CX4 0x10F9
|
||||
#define IXGBE_DEV_ID_82599_SFP 0x10FB
|
||||
#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9
|
||||
#define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0
|
||||
#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A
|
||||
#define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529
|
||||
|
@ -66,6 +140,7 @@
|
|||
#define IXGBE_DEV_ID_82599_T3_LOM 0x151C
|
||||
#define IXGBE_DEV_ID_82599_LS 0x154F
|
||||
#define IXGBE_DEV_ID_X540T 0x1528
|
||||
#endif
|
||||
|
||||
/* General Registers */
|
||||
#define IXGBE_CTRL 0x00000
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/delay.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
|
||||
#include <linux/sched/signal.h>
|
||||
#endif
|
||||
|
||||
#include <exec-env/rte_kni_common.h>
|
||||
#include <kni_fifo.h>
|
||||
|
|
|
@ -63,6 +63,7 @@ struct ____cacheline_aligned ps_context {
|
|||
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
|
||||
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
||||
{
|
||||
unsigned int sum;
|
||||
|
@ -92,6 +93,60 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
|||
: "memory");
|
||||
return (__sum16)sum;
|
||||
}
|
||||
#else
|
||||
#define __force
|
||||
typedef unsigned int u32;
|
||||
|
||||
static inline __sum16 csum_fold(__wsum csum)
|
||||
{
|
||||
u32 sum = (__force u32)csum;;
|
||||
|
||||
sum += (sum << 16);
|
||||
csum = (sum < csum);
|
||||
sum >>= 16;
|
||||
sum += csum;
|
||||
|
||||
return (__force __sum16)~sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a version of ip_compute_csum() optimized for IP headers,
|
||||
* which always checksum on 4 octet boundaries.
|
||||
*
|
||||
* By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
|
||||
* Arnt Gulbrandsen.
|
||||
*/
|
||||
static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
||||
{
|
||||
const unsigned int *word = iph;
|
||||
const unsigned int *stop = word + ihl;
|
||||
unsigned int csum;
|
||||
int carry;
|
||||
|
||||
csum = word[0];
|
||||
csum += word[1];
|
||||
carry = (csum < word[1]);
|
||||
csum += carry;
|
||||
|
||||
csum += word[2];
|
||||
carry = (csum < word[2]);
|
||||
csum += carry;
|
||||
|
||||
csum += word[3];
|
||||
carry = (csum < word[3]);
|
||||
csum += carry;
|
||||
|
||||
word += 4;
|
||||
do {
|
||||
csum += *word;
|
||||
carry = (csum < *word);
|
||||
csum += carry;
|
||||
word++;
|
||||
} while (word != stop);
|
||||
|
||||
return csum_fold(csum);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# TODO: Make this Makefile.in pretty
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
@ -5,6 +6,7 @@
|
|||
PS=@PSIO@
|
||||
DPDK=@DPDK@
|
||||
NETMAP=@NETMAP@
|
||||
ONVM=@ONVM@
|
||||
LRO=@LRO@
|
||||
HWCSUM=@HWCSUM@
|
||||
MTCP_LIB_DIR=../lib
|
||||
|
@ -12,30 +14,27 @@ MTCP_LIB=libmtcp.a
|
|||
MTCP_HDR_DIR=../include
|
||||
MTCP_HDR = mtcp_api.h mtcp_epoll.h
|
||||
|
||||
|
||||
### Check onvm related env vars ###
|
||||
ifeq ($(RTE_SDK),)
|
||||
$(error "Please define RTE_SDK environment variable")
|
||||
endif
|
||||
|
||||
ifeq ($(ONVM),)
|
||||
$(error "Please define ONVM environment variable")
|
||||
endif
|
||||
|
||||
### GCC ###
|
||||
GCC=@CC@
|
||||
|
||||
### FLAGS ###
|
||||
GCC_OPT = -m64 -Wall -fPIC -fgnu89-inline -Werror
|
||||
ifeq ($(shell uname -m),x86_64)
|
||||
GCC_OPT = -m64
|
||||
else
|
||||
GCC_OPT =
|
||||
endif
|
||||
GCC_OPT += -Wall -fPIC -fgnu89-inline -Werror
|
||||
#DBG_OPT = -DDBGMSG -DDBGFUNC -DSTREAM -DSTATE -DTSTAT -DAPP -DEPOLL
|
||||
#DBG_OPT = -DDBGMSG -DDBGFUNC -DSTREAM -DSTATE
|
||||
#DBG_OPT += -DPKTDUMP
|
||||
#DBG_OPT += -DDUMP_STREAM
|
||||
#GCC_OPT += -g -DNETSTAT -DINFO -DDBGERR -DDBGCERR
|
||||
GCC_OPT += -DNDEBUG -O3 -DNETSTAT -DINFO -DDBGERR -DDBGCERR
|
||||
GCC_OPT += -DNDEBUG -g -O3 -DNETSTAT -DINFO -DDBGERR -DDBGCERR
|
||||
#GCC_OPT += -DNDEBUG -g -DNETSTAT -DINFO -DDBGERR -DDBGCERR
|
||||
GCC_OPT += $(DBG_OPT)
|
||||
|
||||
CFLAGS=@CFLAGS@
|
||||
|
||||
ifeq ($(LRO),1)
|
||||
GCC_OPT += -DENABLELRO
|
||||
endif
|
||||
|
@ -48,9 +47,6 @@ endif
|
|||
INC_DIR=./include
|
||||
INC= -I$(INC_DIR)
|
||||
|
||||
INC += -I$(ONVM)/onvm_nflib
|
||||
LDFLAGS += $(ONVM)/onvm_nflib/onvm_nflib/$(RTE_TARGET)/libonvm.a
|
||||
|
||||
ifeq ($(PS),1)
|
||||
LIBS = -lps
|
||||
else
|
||||
|
@ -63,6 +59,16 @@ else
|
|||
INC += -DDISABLE_NETMAP
|
||||
endif
|
||||
|
||||
ifeq ($(ONVM),1)
|
||||
ifeq ($(RTE_TARGET),)
|
||||
$(error "Please define RTE_SDK environment variable")
|
||||
endif
|
||||
INC += -I@ONVMLIBPATH@/onvm_nflib
|
||||
INC += -DENABLE_ONVM
|
||||
LDFLAGS += @ONVMLIBPATH@/onvm_nflib/onvm_nflib/$(RTE_TARGET)/libonvm.a
|
||||
endif
|
||||
|
||||
|
||||
# PacketShader LIBRARY and HEADER
|
||||
PS_DIR=../../io_engine
|
||||
INC += -I$(PS_DIR)/include
|
||||
|
@ -83,14 +89,6 @@ else
|
|||
GCC_OPT += -DHUGEPAGE
|
||||
endif
|
||||
|
||||
ifeq ($V,) # no echo
|
||||
export MSG=@echo
|
||||
export HIDE=@
|
||||
else
|
||||
export MSG=@\#
|
||||
export HIDE=
|
||||
endif
|
||||
|
||||
### SOURCE CODE ###
|
||||
SRCS = core.c tcp_stream.c config.c api.c eventpoll.c socket.c pipe.c \
|
||||
tcp_util.c eth_in.c ip_in.c tcp_in.c eth_out.c ip_out.c tcp_out.c \
|
||||
|
@ -101,6 +99,13 @@ SRCS = core.c tcp_stream.c config.c api.c eventpoll.c socket.c pipe.c \
|
|||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
DEPS = $(patsubst %.c,.%.d,$(SRCS))
|
||||
|
||||
ifeq ($V,) # no echo
|
||||
export MSG=@echo
|
||||
export HIDE=@
|
||||
else
|
||||
export MSG=@\#
|
||||
export HIDE=
|
||||
endif
|
||||
|
||||
### GOALS ###
|
||||
all: default
|
||||
|
@ -111,7 +116,7 @@ default: $(OBJS) $(MTCP_HDR)
|
|||
|
||||
$(OBJS): %.o: %.c Makefile
|
||||
$(MSG) " CC $<"
|
||||
$(HIDE) $(GCC) $(GCC_OPT) $(INC) -c $< -o $@
|
||||
$(HIDE) $(GCC) $(CFLAGS) $(GCC_OPT) $(INC) -c $< -o $@
|
||||
$(DEPS): .%.d: %.c Makefile
|
||||
$(HIDE) $(GCC) $(GCC_OPT) $(INC) -MM $(CFLAGS) $< > $@
|
||||
|
||||
|
|
|
@ -112,8 +112,12 @@ CreateAddressPoolPerCore(int core, int num_queues,
|
|||
uint32_t saddr_h, daddr_h;
|
||||
uint16_t sport_h, dport_h;
|
||||
int rss_core;
|
||||
#if 0
|
||||
uint8_t endian_check = (current_iomodule_func == &dpdk_module_func) ?
|
||||
0 : 1;
|
||||
#else
|
||||
uint8_t endian_check = FetchEndianType();
|
||||
#endif
|
||||
|
||||
ap = (addr_pool_t)calloc(1, sizeof(struct addr_pool));
|
||||
if (!ap)
|
||||
|
@ -216,8 +220,12 @@ FetchAddress(addr_pool_t ap, int core, int num_queues,
|
|||
struct addr_entry *walk, *next;
|
||||
int rss_core;
|
||||
int ret = -1;
|
||||
#if 0
|
||||
uint8_t endian_check = (current_iomodule_func == &dpdk_module_func) ?
|
||||
0 : 1;
|
||||
#else
|
||||
uint8_t endian_check = FetchEndianType();
|
||||
#endif
|
||||
|
||||
if (!ap || !daddr || !saddr)
|
||||
return -1;
|
||||
|
@ -265,6 +273,34 @@ FetchAddress(addr_pool_t ap, int core, int num_queues,
|
|||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
FetchAddressPerCore(addr_pool_t ap, int core, int num_queues,
|
||||
const struct sockaddr_in *daddr, struct sockaddr_in *saddr)
|
||||
{
|
||||
struct addr_entry *walk;
|
||||
int ret = -1;
|
||||
|
||||
if (!ap || !daddr || !saddr)
|
||||
return -1;
|
||||
|
||||
pthread_mutex_lock(&ap->lock);
|
||||
|
||||
/* we don't need to calculate RSSCPUCore if mtcp_init_rss is called */
|
||||
walk = TAILQ_FIRST(&ap->free_list);
|
||||
if (walk) {
|
||||
*saddr = walk->addr;
|
||||
TAILQ_REMOVE(&ap->free_list, walk, addr_link);
|
||||
TAILQ_INSERT_TAIL(&ap->used_list, walk, addr_link);
|
||||
ap->num_free--;
|
||||
ap->num_used++;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ap->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
FreeAddress(addr_pool_t ap, const struct sockaddr_in *addr)
|
||||
{
|
||||
struct addr_entry *walk, *next;
|
||||
|
@ -280,7 +316,7 @@ FreeAddress(addr_pool_t ap, const struct sockaddr_in *addr)
|
|||
uint16_t port_h = ntohs(addr->sin_port);
|
||||
int index = addr_h - ap->addr_base;
|
||||
|
||||
if (index >= 0 || index < ap->num_addr) {
|
||||
if (index >= 0 && index < ap->num_addr) {
|
||||
walk = ap->mapper[addr_h - ap->addr_base].addrmap[port_h];
|
||||
} else {
|
||||
walk = NULL;
|
||||
|
|
|
@ -46,7 +46,7 @@ GetMTCPManager(mctx_t mctx)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (mctx->cpu < 0) {
|
||||
if (mctx->cpu < 0 || mctx->cpu >= num_cpus) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ mtcp_socket(mctx_t mctx, int domain, int type, int protocol)
|
|||
}
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
type = MTCP_SOCK_STREAM;
|
||||
type = (int)MTCP_SOCK_STREAM;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
@ -525,16 +525,21 @@ mtcp_listen(mctx_t mctx, int sockid, int backlog)
|
|||
listener->socket = &mtcp->smap[sockid];
|
||||
|
||||
if (pthread_cond_init(&listener->accept_cond, NULL)) {
|
||||
/* errno set internally */
|
||||
perror("pthread_cond_init of ctx->accept_cond\n");
|
||||
free(listener);
|
||||
return -1;
|
||||
}
|
||||
if (pthread_mutex_init(&listener->accept_lock, NULL)) {
|
||||
/* errno set internally */
|
||||
perror("pthread_mutex_init of ctx->accept_lock\n");
|
||||
free(listener);
|
||||
return -1;
|
||||
}
|
||||
|
||||
listener->acceptq = CreateStreamQueue(backlog);
|
||||
if (!listener->acceptq) {
|
||||
free(listener);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
@ -644,16 +649,23 @@ mtcp_init_rss(mctx_t mctx, in_addr_t saddr_base, int num_addr,
|
|||
|
||||
mtcp = GetMTCPManager(mctx);
|
||||
if (!mtcp) {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (saddr_base == INADDR_ANY) {
|
||||
int nif_out;
|
||||
int nif_out, eidx;
|
||||
|
||||
/* for the INADDR_ANY, find the output interface for the destination
|
||||
and set the saddr_base as the ip address of the output interface */
|
||||
nif_out = GetOutputInterface(daddr);
|
||||
saddr_base = CONFIG.eths[nif_out].ip_addr;
|
||||
if (nif_out < 0) {
|
||||
errno = EINVAL;
|
||||
TRACE_DBG("Could not determine nif idx!\n");
|
||||
return -1;
|
||||
}
|
||||
eidx = CONFIG.nif_to_eidx[nif_out];
|
||||
saddr_base = CONFIG.eths[eidx].ip_addr;
|
||||
}
|
||||
|
||||
ap = CreateAddressPoolPerCore(mctx->cpu, num_cpus,
|
||||
|
@ -679,7 +691,7 @@ mtcp_connect(mctx_t mctx, int sockid,
|
|||
in_addr_t dip;
|
||||
in_port_t dport;
|
||||
int is_dyn_bound = FALSE;
|
||||
int ret;
|
||||
int ret, nif;
|
||||
|
||||
mtcp = GetMTCPManager(mctx);
|
||||
if (!mtcp) {
|
||||
|
@ -737,8 +749,12 @@ mtcp_connect(mctx_t mctx, int sockid,
|
|||
socket->saddr.sin_port != INPORT_ANY &&
|
||||
socket->saddr.sin_addr.s_addr != INADDR_ANY) {
|
||||
int rss_core;
|
||||
#if 0
|
||||
uint8_t endian_check = (current_iomodule_func == &dpdk_module_func) ?
|
||||
0 : 1;
|
||||
#else
|
||||
uint8_t endian_check = FetchEndianType();
|
||||
#endif
|
||||
|
||||
rss_core = GetRSSCPUCore(socket->saddr.sin_addr.s_addr, dip,
|
||||
socket->saddr.sin_port, dport, num_queues, endian_check);
|
||||
|
@ -749,10 +765,15 @@ mtcp_connect(mctx_t mctx, int sockid,
|
|||
}
|
||||
} else {
|
||||
if (mtcp->ap) {
|
||||
ret = FetchAddress(mtcp->ap,
|
||||
mctx->cpu, num_queues, addr_in, &socket->saddr);
|
||||
ret = FetchAddressPerCore(mtcp->ap,
|
||||
mctx->cpu, num_queues, addr_in, &socket->saddr);
|
||||
} else {
|
||||
ret = FetchAddress(ap[GetOutputInterface(dip)],
|
||||
nif = GetOutputInterface(dip);
|
||||
if (nif < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
ret = FetchAddress(ap[nif],
|
||||
mctx->cpu, num_queues, addr_in, &socket->saddr);
|
||||
}
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -140,10 +140,11 @@ ARPOutput(struct mtcp_manager *mtcp, int nif, int opcode,
|
|||
arph->ar_op = htons(opcode);
|
||||
|
||||
/* Fill arp body */
|
||||
arph->ar_sip = CONFIG.eths[nif].ip_addr;
|
||||
int edix = CONFIG.nif_to_eidx[nif];
|
||||
arph->ar_sip = CONFIG.eths[edix].ip_addr;
|
||||
arph->ar_tip = dst_ip;
|
||||
|
||||
memcpy(arph->ar_sha, CONFIG.eths[nif].haddr, arph->ar_hln);
|
||||
memcpy(arph->ar_sha, CONFIG.eths[edix].haddr, arph->ar_hln);
|
||||
if (target_haddr) {
|
||||
memcpy(arph->ar_tha, target_haddr, arph->ar_hln);
|
||||
} else {
|
||||
|
@ -255,7 +256,7 @@ ProcessARPPacket(mtcp_manager_t mtcp, uint32_t cur_ts,
|
|||
const int ifidx, unsigned char *pkt_data, int len)
|
||||
{
|
||||
struct arphdr *arph = (struct arphdr *)(pkt_data + sizeof(struct ethhdr));
|
||||
int i;
|
||||
int i, nif;
|
||||
int to_me = FALSE;
|
||||
|
||||
/* process the arp messages destined to me */
|
||||
|
@ -274,7 +275,8 @@ ProcessARPPacket(mtcp_manager_t mtcp, uint32_t cur_ts,
|
|||
|
||||
switch (ntohs(arph->ar_op)) {
|
||||
case arp_op_request:
|
||||
ProcessARPRequest(mtcp, arph, ifidx, cur_ts);
|
||||
nif = CONFIG.eths[ifidx].ifindex; // use the port index as argument
|
||||
ProcessARPRequest(mtcp, arph, nif, cur_ts);
|
||||
break;
|
||||
|
||||
case arp_op_reply:
|
||||
|
@ -294,11 +296,11 @@ ProcessARPPacket(mtcp_manager_t mtcp, uint32_t cur_ts,
|
|||
void
|
||||
ARPTimer(mtcp_manager_t mtcp, uint32_t cur_ts)
|
||||
{
|
||||
struct arp_queue_entry *ent;
|
||||
struct arp_queue_entry *ent, *ent_tmp;
|
||||
|
||||
/* if the arp requet is timed out, retransmit */
|
||||
pthread_mutex_lock(&g_arpm.lock);
|
||||
TAILQ_FOREACH(ent, &g_arpm.list, arp_link) {
|
||||
TAILQ_FOREACH_SAFE(ent, &g_arpm.list, arp_link, ent_tmp) {
|
||||
if (TCP_SEQ_GT(cur_ts, ent->ts_out + SEC_TO_TS(ARP_TIMEOUT_SEC))) {
|
||||
TRACE_INFO("[CPU%2d] ARP request timed out.\n",
|
||||
mtcp->ctx->cpu);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "mtcp.h"
|
||||
#include "config.h"
|
||||
|
@ -29,6 +30,29 @@ struct mtcp_manager *g_mtcp[MAX_CPUS] = {NULL};
|
|||
struct mtcp_config CONFIG = {0};
|
||||
addr_pool_t ap[ETH_NUM] = {NULL};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static inline int
|
||||
mystrtol(const char *nptr, int base)
|
||||
{
|
||||
int rval;
|
||||
char *endptr;
|
||||
|
||||
errno = 0;
|
||||
rval = strtol(nptr, &endptr, 10);
|
||||
/* check for strtol errors */
|
||||
if ((errno == ERANGE && (rval == LONG_MAX ||
|
||||
rval == LONG_MIN))
|
||||
|| (errno != 0 && rval == 0)) {
|
||||
perror("strtol");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (endptr == nptr) {
|
||||
TRACE_CONFIG("Parsing strtol error!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int
|
||||
GetIntValue(char* value)
|
||||
{
|
||||
|
@ -66,6 +90,7 @@ EnrollRouteTableEntry(char *optstr)
|
|||
int i;
|
||||
char * saveptr;
|
||||
|
||||
saveptr = NULL;
|
||||
daddr_s = strtok_r(optstr, "/", &saveptr);
|
||||
prefix = strtok_r(NULL, " ", &saveptr);
|
||||
dev = strtok_r(NULL, "\n", &saveptr);
|
||||
|
@ -88,7 +113,8 @@ EnrollRouteTableEntry(char *optstr)
|
|||
TRACE_CONFIG("Interface %s does not exist!\n", dev);
|
||||
exit(4);
|
||||
}
|
||||
} else if (current_iomodule_func == &dpdk_module_func) {
|
||||
} else if (current_iomodule_func == &dpdk_module_func ||
|
||||
current_iomodule_func == &onvm_module_func) {
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
if (strcmp(CONFIG.eths[i].dev_name, dev))
|
||||
continue;
|
||||
|
@ -99,7 +125,7 @@ EnrollRouteTableEntry(char *optstr)
|
|||
|
||||
ridx = CONFIG.routes++;
|
||||
CONFIG.rtable[ridx].daddr = inet_addr(daddr_s);
|
||||
CONFIG.rtable[ridx].prefix = atoi(prefix);
|
||||
CONFIG.rtable[ridx].prefix = mystrtol(prefix, 10);
|
||||
if (CONFIG.rtable[ridx].prefix > 32 || CONFIG.rtable[ridx].prefix < 0) {
|
||||
TRACE_CONFIG("Prefix length should be between 0 - 32.\n");
|
||||
exit(4);
|
||||
|
@ -200,6 +226,7 @@ ParseMACAddress(unsigned char *haddr, char *haddr_str)
|
|||
unsigned int temp;
|
||||
char *saveptr = NULL;
|
||||
|
||||
saveptr = NULL;
|
||||
str = strtok_r(haddr_str, ":", &saveptr);
|
||||
i = 0;
|
||||
while (str != NULL) {
|
||||
|
@ -207,7 +234,10 @@ ParseMACAddress(unsigned char *haddr, char *haddr_str)
|
|||
TRACE_CONFIG("MAC address length exceeds %d!\n", ETH_ALEN);
|
||||
exit(4);
|
||||
}
|
||||
sscanf(str, "%x", &temp);
|
||||
if (sscanf(str, "%x", &temp) < 1) {
|
||||
TRACE_CONFIG("sscanf failed!\n");
|
||||
exit(4);
|
||||
}
|
||||
haddr[i++] = temp;
|
||||
str = strtok_r(NULL, ":", &saveptr);
|
||||
}
|
||||
|
@ -315,7 +345,8 @@ EnrollARPTableEntry(char *optstr)
|
|||
int idx;
|
||||
|
||||
char *saveptr;
|
||||
|
||||
|
||||
saveptr = NULL;
|
||||
dip_s = strtok_r(optstr, "/", &saveptr);
|
||||
prefix_s = strtok_r(NULL, " ", &saveptr);
|
||||
daddr_s = strtok_r(NULL, "\n", &saveptr);
|
||||
|
@ -327,7 +358,7 @@ EnrollARPTableEntry(char *optstr)
|
|||
if (prefix_s == NULL)
|
||||
prefix = 32;
|
||||
else
|
||||
prefix = atoi(prefix_s);
|
||||
prefix = mystrtol(prefix_s, 10);
|
||||
|
||||
if (prefix > 32 || prefix < 0) {
|
||||
TRACE_CONFIG("Prefix length should be between 0 - 32.\n");
|
||||
|
@ -438,12 +469,13 @@ SetMultiProcessSupport(char *multiprocess_details)
|
|||
|
||||
TRACE_CONFIG("Loading multi-process configuration\n");
|
||||
|
||||
saveptr = NULL;
|
||||
sample = strtok_r(multiprocess_details, token, &saveptr);
|
||||
if (sample == NULL) {
|
||||
TRACE_CONFIG("No option for multi-process support given!\n");
|
||||
return -1;
|
||||
}
|
||||
CONFIG.multi_process_curr_core = atoi(sample);
|
||||
CONFIG.multi_process_curr_core = mystrtol(sample, 10);
|
||||
|
||||
sample = strtok_r(NULL, token, &saveptr);
|
||||
if (sample != NULL && !strcmp(sample, "master"))
|
||||
|
@ -461,6 +493,7 @@ ParseConfiguration(char *line)
|
|||
char *saveptr;
|
||||
|
||||
strncpy(optstr, line, MAX_OPTLINE_LEN - 1);
|
||||
saveptr = NULL;
|
||||
|
||||
p = strtok_r(optstr, " \t=", &saveptr);
|
||||
if (p == NULL) {
|
||||
|
@ -475,7 +508,7 @@ ParseConfiguration(char *line)
|
|||
}
|
||||
|
||||
if (strcmp(p, "num_cores") == 0) {
|
||||
CONFIG.num_cores = atoi(q);
|
||||
CONFIG.num_cores = mystrtol(q, 10);
|
||||
if (CONFIG.num_cores <= 0) {
|
||||
TRACE_CONFIG("Number of cores should be larger than 0.\n");
|
||||
return -1;
|
||||
|
@ -487,36 +520,36 @@ ParseConfiguration(char *line)
|
|||
}
|
||||
num_cpus = CONFIG.num_cores;
|
||||
} else if (strcmp(p, "max_concurrency") == 0) {
|
||||
CONFIG.max_concurrency = atoi(q);
|
||||
CONFIG.max_concurrency = mystrtol(q, 10);
|
||||
if (CONFIG.max_concurrency < 0) {
|
||||
TRACE_CONFIG("The maximum concurrency should be larger than 0.\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(p, "max_num_buffers") == 0) {
|
||||
CONFIG.max_num_buffers = atoi(q);
|
||||
CONFIG.max_num_buffers = mystrtol(q, 10);
|
||||
if (CONFIG.max_num_buffers < 0) {
|
||||
TRACE_CONFIG("The maximum # buffers should be larger than 0.\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(p, "rcvbuf") == 0) {
|
||||
CONFIG.rcvbuf_size = atoi(q);
|
||||
CONFIG.rcvbuf_size = mystrtol(q, 10);
|
||||
if (CONFIG.rcvbuf_size < 64) {
|
||||
TRACE_CONFIG("Receive buffer size should be larger than 64.\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(p, "sndbuf") == 0) {
|
||||
CONFIG.sndbuf_size = atoi(q);
|
||||
CONFIG.sndbuf_size = mystrtol(q, 10);
|
||||
if (CONFIG.sndbuf_size < 64) {
|
||||
TRACE_CONFIG("Send buffer size should be larger than 64.\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(p, "tcp_timeout") == 0) {
|
||||
CONFIG.tcp_timeout = atoi(q);
|
||||
CONFIG.tcp_timeout = mystrtol(q, 10);
|
||||
if (CONFIG.tcp_timeout > 0) {
|
||||
CONFIG.tcp_timeout = SEC_TO_USEC(CONFIG.tcp_timeout) / TIME_TICK;
|
||||
}
|
||||
} else if (strcmp(p, "tcp_timewait") == 0) {
|
||||
CONFIG.tcp_timewait = atoi(q);
|
||||
CONFIG.tcp_timewait = mystrtol(q, 10);
|
||||
if (CONFIG.tcp_timewait > 0) {
|
||||
CONFIG.tcp_timewait = SEC_TO_USEC(CONFIG.tcp_timewait) / TIME_TICK;
|
||||
}
|
||||
|
@ -537,7 +570,15 @@ ParseConfiguration(char *line)
|
|||
} else if (strcmp(p, "io") == 0) {
|
||||
AssignIOModule(q);
|
||||
} else if (strcmp(p, "num_mem_ch") == 0) {
|
||||
CONFIG.num_mem_ch = atoi(q);
|
||||
CONFIG.num_mem_ch = mystrtol(q, 10);
|
||||
#ifdef ENABLE_ONVM
|
||||
} else if (strcmp(p, "onvm_inst") == 0) {
|
||||
CONFIG.onvm_inst = mystrtol(q, 10);
|
||||
} else if (strcmp(p, "onvm_serv") == 0) {
|
||||
CONFIG.onvm_serv = mystrtol(q, 10);
|
||||
} else if (strcmp(p, "onvm_dest") == 0) {
|
||||
CONFIG.onvm_dest = mystrtol(q, 10);
|
||||
#endif
|
||||
} else if (strcmp(p, "multiprocess") == 0) {
|
||||
CONFIG.multi_process = 1;
|
||||
SetMultiProcessSupport(line + strlen(p) + 1);
|
||||
|
@ -575,7 +616,11 @@ LoadConfiguration(const char *fname)
|
|||
CONFIG.tcp_timeout = TCP_TIMEOUT;
|
||||
CONFIG.tcp_timewait = TCP_TIMEWAIT;
|
||||
CONFIG.num_mem_ch = 0;
|
||||
|
||||
#ifdef ENABLE_ONVM
|
||||
CONFIG.onvm_inst = (uint16_t) -1;
|
||||
CONFIG.onvm_dest = (uint16_t) -1;
|
||||
CONFIG.onvm_serv = (uint16_t) -1;
|
||||
#endif
|
||||
while (1) {
|
||||
char *p;
|
||||
char *temp;
|
||||
|
@ -597,8 +642,10 @@ LoadConfiguration(const char *fname)
|
|||
if (*p == 0) /* nothing more to process? */
|
||||
continue;
|
||||
|
||||
if (ParseConfiguration(p) < 0)
|
||||
if (ParseConfiguration(p) < 0) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
@ -637,9 +684,6 @@ PrintConfiguration()
|
|||
}
|
||||
TRACE_CONFIG("TCP timewait seconds: %d\n",
|
||||
USEC_TO_SEC(CONFIG.tcp_timewait * TIME_TICK));
|
||||
TRACE_CONFIG("Instance ID: %d\n", CONFIG.instance_id);
|
||||
TRACE_CONFIG("Service ID: %d\n", CONFIG.service_id);
|
||||
TRACE_CONFIG("Destination ID: %d\n", CONFIG.dest_id);
|
||||
TRACE_CONFIG("NICs to print statistics:");
|
||||
for (i = 0; i < CONFIG.eths_num; i++) {
|
||||
if (CONFIG.eths[i].stat_print) {
|
||||
|
|
149
mtcp/src/core.c
149
mtcp/src/core.c
|
@ -35,6 +35,10 @@
|
|||
#include <rte_lcore.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ONVM
|
||||
#include "onvm_nflib.h"
|
||||
#endif
|
||||
|
||||
#define PS_CHUNK_SIZE 64
|
||||
#define RX_THRESH (PS_CHUNK_SIZE * 0.8)
|
||||
|
||||
|
@ -70,6 +74,8 @@ static int sigint_cnt[MAX_CPUS] = {0};
|
|||
static struct timespec sigint_ts[MAX_CPUS];
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int mtcp_master = -1;
|
||||
void
|
||||
mtcp_free_context(mctx_t mctx);
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
HandleSignal(int signal)
|
||||
|
@ -80,7 +86,9 @@ HandleSignal(int signal)
|
|||
int core;
|
||||
struct timespec cur_ts;
|
||||
|
||||
#ifdef ENABLE_ONVM
|
||||
onvm_nflib_stop();
|
||||
#endif
|
||||
core = sched_getcpu();
|
||||
clock_gettime(CLOCK_REALTIME, &cur_ts);
|
||||
|
||||
|
@ -265,7 +273,7 @@ PrintNetworkStats(mtcp_manager_t mtcp, uint32_t cur_ts)
|
|||
mtcp->p_nstat_ts = cur_ts;
|
||||
gflow_cnt = 0;
|
||||
memset(&g_nstat, 0, sizeof(struct net_stat));
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
for (i = 0; i < CONFIG.num_cores; i++) {
|
||||
if (running[i]) {
|
||||
PrintThreadNetworkStats(g_mtcp[i], &ns);
|
||||
#if NETSTAT_TOTAL
|
||||
|
@ -892,7 +900,7 @@ InitializeMTCPManager(struct mtcp_thread_context* ctx)
|
|||
mtcp = (mtcp_manager_t)calloc(1, sizeof(struct mtcp_manager));
|
||||
if (!mtcp) {
|
||||
perror("malloc");
|
||||
CTRACE_ERROR("Failed to allocate mtcp_manager.\n");
|
||||
fprintf(stderr, "Failed to allocate mtcp_manager.\n");
|
||||
return NULL;
|
||||
}
|
||||
g_mtcp[ctx->cpu] = mtcp;
|
||||
|
@ -1121,6 +1129,9 @@ MTCPRunThread(void *arg)
|
|||
/* start the main loop */
|
||||
RunMainLoop(ctx);
|
||||
|
||||
struct mtcp_context m;
|
||||
m.cpu = cpu;
|
||||
mtcp_free_context(&m);
|
||||
/* destroy hash tables */
|
||||
DestroyHashtable(g_mtcp[cpu]->tcp_flow_table);
|
||||
DestroyHashtable(g_mtcp[cpu]->listeners);
|
||||
|
@ -1130,27 +1141,26 @@ MTCPRunThread(void *arg)
|
|||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#ifndef DISABLE_DPDK
|
||||
static int MTCPDPDKRunThread(void *arg)
|
||||
{
|
||||
MTCPRunThread(arg);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
mctx_t
|
||||
mtcp_create_context(int cpu)
|
||||
{
|
||||
mctx_t mctx;
|
||||
int ret;
|
||||
|
||||
/* check if mtcp_create_context() was already initialized */
|
||||
if (g_logctx[cpu] != NULL) {
|
||||
TRACE_ERROR("%s was already initialized before!\n",
|
||||
__FUNCTION__);
|
||||
if (cpu >= CONFIG.num_cores) {
|
||||
TRACE_ERROR("Failed initialize new mtcp context. "
|
||||
"Requested cpu id %d exceed the number of cores %d configured to use.\n",
|
||||
cpu, CONFIG.num_cores);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check if mtcp_create_context() was already initialized */
|
||||
if (g_logctx[cpu] != NULL) {
|
||||
TRACE_ERROR("%s was already initialized before!\n",
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = sem_init(&g_init_sem[cpu], 0, 0);
|
||||
if (ret) {
|
||||
TRACE_ERROR("Failed initialize init_sem.\n");
|
||||
|
@ -1168,8 +1178,9 @@ mtcp_create_context(int cpu)
|
|||
g_logctx[cpu] = (struct log_thread_context *)
|
||||
calloc(1, sizeof(struct log_thread_context));
|
||||
if (!g_logctx[cpu]) {
|
||||
perror("malloc");
|
||||
perror("calloc");
|
||||
TRACE_ERROR("Failed to allocate memory for log thread context.\n");
|
||||
free(mctx);
|
||||
return NULL;
|
||||
}
|
||||
InitLogThreadContext(g_logctx[cpu], cpu);
|
||||
|
@ -1177,31 +1188,15 @@ mtcp_create_context(int cpu)
|
|||
NULL, ThreadLogMain, (void *)g_logctx[cpu])) {
|
||||
perror("pthread_create");
|
||||
TRACE_ERROR("Failed to create log thread\n");
|
||||
free(g_logctx[cpu]);
|
||||
free(mctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Wake up mTCP threads (wake up I/O threads) */
|
||||
if (current_iomodule_func == &dpdk_module_func) {
|
||||
#ifndef DISABLE_DPDK
|
||||
int master;
|
||||
master = rte_get_master_lcore();
|
||||
if (master == cpu) {
|
||||
lcore_config[master].ret = 0;
|
||||
lcore_config[master].state = FINISHED;
|
||||
if (pthread_create(&g_thread[cpu],
|
||||
NULL, MTCPRunThread, (void *)mctx) != 0) {
|
||||
TRACE_ERROR("pthread_create of mtcp thread failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
rte_eal_remote_launch(MTCPDPDKRunThread, mctx, cpu);
|
||||
#endif /* !DISABLE_DPDK */
|
||||
} else {
|
||||
if (pthread_create(&g_thread[cpu],
|
||||
NULL, MTCPRunThread, (void *)mctx) != 0) {
|
||||
TRACE_ERROR("pthread_create of mtcp thread failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
if (pthread_create(&g_thread[cpu],
|
||||
NULL, MTCPRunThread, (void *)mctx) != 0) {
|
||||
TRACE_ERROR("pthread_create of mtcp thread failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sem_wait(&g_init_sem[cpu]);
|
||||
|
@ -1217,14 +1212,25 @@ mtcp_create_context(int cpu)
|
|||
return mctx;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
void
|
||||
mtcp_destroy_context(mctx_t mctx)
|
||||
{
|
||||
struct mtcp_thread_context *ctx = g_pctx[mctx->cpu];
|
||||
if (ctx != NULL)
|
||||
ctx->done = 1;
|
||||
free(mctx);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtcp_free_context(mctx_t mctx)
|
||||
{
|
||||
struct mtcp_thread_context *ctx = g_pctx[mctx->cpu];
|
||||
struct mtcp_manager *mtcp = ctx->mtcp_manager;
|
||||
struct log_thread_context *log_ctx = mtcp->logger;
|
||||
int ret, i;
|
||||
|
||||
if (g_pctx[mctx->cpu] == NULL) return;
|
||||
|
||||
TRACE_DBG("CPU %d: mtcp_destroy_context()\n", mctx->cpu);
|
||||
|
||||
/* close all stream sockets that are still open */
|
||||
|
@ -1244,6 +1250,7 @@ mtcp_destroy_context(mctx_t mctx)
|
|||
ctx->done = 1;
|
||||
|
||||
//pthread_kill(g_thread[mctx->cpu], SIGINT);
|
||||
#if 0
|
||||
/* XXX - dpdk logic changes */
|
||||
if (current_iomodule_func == &dpdk_module_func) {
|
||||
#ifndef DISABLE_DPDK
|
||||
|
@ -1254,7 +1261,10 @@ mtcp_destroy_context(mctx_t mctx)
|
|||
rte_eal_wait_lcore(mctx->cpu);
|
||||
#endif /* !DISABLE_DPDK */
|
||||
} else
|
||||
pthread_join(g_thread[mctx->cpu], NULL);
|
||||
#endif
|
||||
{
|
||||
pthread_join(g_thread[mctx->cpu], NULL);
|
||||
}
|
||||
|
||||
TRACE_INFO("MTCP thread %d joined.\n", mctx->cpu);
|
||||
running[mctx->cpu] = FALSE;
|
||||
|
@ -1320,6 +1330,7 @@ mtcp_destroy_context(mctx_t mctx)
|
|||
|
||||
if (mtcp->ap) {
|
||||
DestroyAddressPool(mtcp->ap);
|
||||
mtcp->ap = NULL;
|
||||
}
|
||||
|
||||
SQ_LOCK_DESTROY(&ctx->connect_lock);
|
||||
|
@ -1332,7 +1343,11 @@ mtcp_destroy_context(mctx_t mctx)
|
|||
//TRACE_INFO("MTCP thread %d destroyed.\n", mctx->cpu);
|
||||
mtcp->iom->destroy_handle(ctx);
|
||||
free(ctx);
|
||||
free(mctx);
|
||||
if (g_logctx[mctx->cpu]) {
|
||||
free(g_logctx[mctx->cpu]);
|
||||
g_logctx[mctx->cpu] = NULL;
|
||||
}
|
||||
g_pctx[mctx->cpu] = NULL;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
mtcp_sighandler_t
|
||||
|
@ -1369,8 +1384,6 @@ mtcp_getconf(struct mtcp_conf *conf)
|
|||
conf->tcp_timewait = CONFIG.tcp_timewait;
|
||||
conf->tcp_timeout = CONFIG.tcp_timeout;
|
||||
|
||||
conf->core_list = CONFIG.core_list;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -1395,8 +1408,6 @@ mtcp_setconf(const struct mtcp_conf *conf)
|
|||
CONFIG.tcp_timewait = conf->tcp_timewait;
|
||||
if (conf->tcp_timeout > 0)
|
||||
CONFIG.tcp_timeout = conf->tcp_timeout;
|
||||
if (conf->core_list)
|
||||
CONFIG.core_list = conf->core_list;
|
||||
|
||||
TRACE_CONFIG("Configuration updated by mtcp_setconf().\n");
|
||||
//PrintConfiguration();
|
||||
|
@ -1405,40 +1416,7 @@ mtcp_setconf(const struct mtcp_conf *conf)
|
|||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
mtcp_parse_args(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Set default values */
|
||||
CONFIG.instance_id = NF_NO_ID;
|
||||
CONFIG.dest_id = (uint16_t) - 1;
|
||||
CONFIG.service_id = (int16_t) -1;
|
||||
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "n:r:d:")) != -1){
|
||||
switch (c) {
|
||||
case 'n':
|
||||
CONFIG.instance_id = (uint16_t) strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'r':
|
||||
CONFIG.service_id = (uint16_t) strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'd':
|
||||
CONFIG.dest_id = (uint16_t) strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CONFIG.service_id == (uint16_t)-1) {
|
||||
/* Service ID is required */
|
||||
fprintf(stderr, "You must provide a nonzero service ID with -r\n");
|
||||
return -1;
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
mtcp_init(const char *config_file, int argc, char *argv[])
|
||||
mtcp_init(const char *config_file)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
@ -1451,30 +1429,23 @@ mtcp_init(const char *config_file, int argc, char *argv[])
|
|||
/* getting cpu and NIC */
|
||||
/* set to max cpus only if user has not arbitrarily set it to lower # */
|
||||
num_cpus = (CONFIG.num_cores == 0) ? GetNumCPUs() : CONFIG.num_cores;
|
||||
|
||||
|
||||
assert(num_cpus >= 1);
|
||||
|
||||
if (num_cpus > MAX_CPUS) {
|
||||
TRACE_ERROR("You cannot run mTCP with more than %d cores due "
|
||||
"to NIC hardware queues restriction. Please disable "
|
||||
"the last %d cores in your system\n",
|
||||
"to your static mTCP configuration. Please disable "
|
||||
"the last %d cores in your system.\n",
|
||||
MAX_CPUS, num_cpus - MAX_CPUS);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
for (i = 0; i < num_cpus; i++) {
|
||||
g_mtcp[i] = NULL;
|
||||
running[i] = FALSE;
|
||||
sigint_cnt[i] = 0;
|
||||
}
|
||||
|
||||
/* Set specific onvm args */
|
||||
ret = mtcp_parse_args(argc, argv);
|
||||
if (ret < 0){
|
||||
TRACE_CONFIG("Error while parsing command line arguments.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LoadConfiguration(config_file);
|
||||
if (ret) {
|
||||
TRACE_CONFIG("Error occured while loading configuration.\n");
|
||||
|
|
|
@ -66,7 +66,13 @@ mtcp_core_affinitize(int cpu)
|
|||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
unused = fscanf(fp, "%d", &phy_id);
|
||||
ret = fscanf(fp, "%d", &phy_id);
|
||||
if (ret != 1) {
|
||||
fclose(fp);
|
||||
perror("Fail to read core id");
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
numa_bitmask_setbit(bmask, phy_id);
|
||||
numa_set_membind(bmask);
|
||||
|
|
|
@ -27,16 +27,22 @@
|
|||
#endif /* !ENABLE_STATS_IOCTL */
|
||||
/* for ip pseudo-chksum */
|
||||
#include <rte_ip.h>
|
||||
//#define IP_DEFRAG 1
|
||||
#ifdef IP_DEFRAG
|
||||
/* for ip defragging */
|
||||
#include <rte_ip_frag.h>
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Essential macros */
|
||||
#define MAX_RX_QUEUE_PER_LCORE MAX_CPUS
|
||||
#define MAX_TX_QUEUE_PER_PORT MAX_CPUS
|
||||
|
||||
#ifdef ENABLELRO
|
||||
#define MBUF_SIZE (16384 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
|
||||
#define BUF_SIZE 16384
|
||||
#else
|
||||
#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
|
||||
#define BUF_SIZE 2048
|
||||
#endif /* !ENABLELRO */
|
||||
#define MBUF_SIZE (BUF_SIZE + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
|
||||
#define NB_MBUF 8192
|
||||
#define MEMPOOL_CACHE_SIZE 256
|
||||
//#define RX_IDLE_ENABLE 1
|
||||
|
@ -70,8 +76,16 @@
|
|||
#define RTE_TEST_RX_DESC_DEFAULT 128
|
||||
#define RTE_TEST_TX_DESC_DEFAULT 128
|
||||
|
||||
static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
|
||||
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
|
||||
/*
|
||||
* Ethernet frame overhead
|
||||
*/
|
||||
|
||||
#define ETHER_IFG 12
|
||||
#define ETHER_PREAMBLE 8
|
||||
#define ETHER_OVR (ETHER_CRC_LEN + ETHER_PREAMBLE + ETHER_IFG)
|
||||
|
||||
static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
|
||||
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* packet memory pools for storing packet bufs */
|
||||
static struct rte_mempool *pktmbuf_pool[MAX_CPUS] = {NULL};
|
||||
|
@ -101,7 +115,8 @@ static struct rte_eth_conf port_conf = {
|
|||
.rx_adv_conf = {
|
||||
.rss_conf = {
|
||||
.rss_key = NULL,
|
||||
.rss_hf = ETH_RSS_TCP
|
||||
.rss_hf = ETH_RSS_TCP | ETH_RSS_UDP |
|
||||
ETH_RSS_IP | ETH_RSS_L2_PAYLOAD
|
||||
},
|
||||
},
|
||||
.txmode = {
|
||||
|
@ -146,6 +161,10 @@ struct dpdk_private_context {
|
|||
#ifdef RX_IDLE_ENABLE
|
||||
uint8_t rx_idle;
|
||||
#endif
|
||||
#ifdef IP_DEFRAG
|
||||
struct rte_ip_frag_tbl *frag_tbl;
|
||||
struct rte_ip_frag_death_row death_row;
|
||||
#endif
|
||||
#ifdef ENABLELRO
|
||||
struct rte_mbuf *cur_rx_m;
|
||||
#endif
|
||||
|
@ -155,6 +174,7 @@ struct dpdk_private_context {
|
|||
} __rte_cache_aligned;
|
||||
|
||||
#ifdef ENABLE_STATS_IOCTL
|
||||
#define DEV_NAME "/dev/dpdk-iface"
|
||||
/**
|
||||
* stats struct passed on from user space to the driver
|
||||
*/
|
||||
|
@ -167,13 +187,20 @@ struct stats_struct {
|
|||
uint8_t dev;
|
||||
};
|
||||
#endif /* !ENABLE_STATS_IOCTL */
|
||||
|
||||
#ifdef IP_DEFRAG
|
||||
/* Should be power of two. */
|
||||
#define IP_FRAG_TBL_BUCKET_ENTRIES 16
|
||||
#define RTE_LOGTYPE_IP_RSMBL RTE_LOGTYPE_USER1
|
||||
#define MAX_FRAG_NUM RTE_LIBRTE_IP_FRAG_MAX_FRAG
|
||||
#endif /* !IP_DEFRAG */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
dpdk_init_handle(struct mtcp_thread_context *ctxt)
|
||||
{
|
||||
struct dpdk_private_context *dpc;
|
||||
int i, j;
|
||||
char mempool_name[20];
|
||||
char mempool_name[RTE_MEMPOOL_NAMESIZE];
|
||||
|
||||
/* create and initialize private I/O module context */
|
||||
ctxt->io_private_context = calloc(1, sizeof(struct dpdk_private_context));
|
||||
|
@ -182,7 +209,7 @@ dpdk_init_handle(struct mtcp_thread_context *ctxt)
|
|||
"Can't allocate memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
sprintf(mempool_name, "mbuf_pool-%d", ctxt->cpu);
|
||||
dpc = (struct dpdk_private_context *)ctxt->io_private_context;
|
||||
dpc->pktmbuf_pool = pktmbuf_pool[ctxt->cpu];
|
||||
|
@ -202,10 +229,32 @@ dpdk_init_handle(struct mtcp_thread_context *ctxt)
|
|||
dpc->wmbufs[j].len = 0;
|
||||
}
|
||||
|
||||
#ifdef IP_DEFRAG
|
||||
int max_flows;
|
||||
int socket;
|
||||
uint64_t frag_cycles;
|
||||
|
||||
max_flows = CONFIG.max_concurrency / CONFIG.num_cores;
|
||||
frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1)
|
||||
/ MS_PER_S * max_flows;
|
||||
socket = rte_lcore_to_socket_id(ctxt->cpu);
|
||||
|
||||
if ((dpc->frag_tbl = rte_ip_frag_table_create(max_flows,
|
||||
IP_FRAG_TBL_BUCKET_ENTRIES,
|
||||
max_flows,
|
||||
frag_cycles,
|
||||
socket)) == NULL) {
|
||||
RTE_LOG(ERR, IP_RSMBL, "ip_frag_tbl_create(%u) on "
|
||||
"lcore: %u for queue: %u failed\n",
|
||||
max_flows, ctxt->cpu, ctxt->cpu);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif /* !IP_DEFRAG */
|
||||
|
||||
#ifdef ENABLE_STATS_IOCTL
|
||||
dpc->fd = open("/dev/dpdk-iface", O_RDWR);
|
||||
dpc->fd = open(DEV_NAME, O_RDWR);
|
||||
if (dpc->fd == -1) {
|
||||
TRACE_ERROR("Can't open /dev/dpdk-iface for context->cpu: %d! "
|
||||
TRACE_ERROR("Can't open " DEV_NAME " for context->cpu: %d! "
|
||||
"Are you using mlx4/mlx5 driver?\n",
|
||||
ctxt->cpu);
|
||||
}
|
||||
|
@ -216,55 +265,55 @@ int
|
|||
dpdk_link_devices(struct mtcp_thread_context *ctxt)
|
||||
{
|
||||
/* linking takes place during mtcp_init() */
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
dpdk_release_pkt(struct mtcp_thread_context *ctxt, int ifidx, unsigned char *pkt_data, int len)
|
||||
{
|
||||
/*
|
||||
/*
|
||||
* do nothing over here - memory reclamation
|
||||
* will take place in dpdk_recv_pkts
|
||||
* will take place in dpdk_recv_pkts
|
||||
*/
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
dpdk_send_pkts(struct mtcp_thread_context *ctxt, int nif)
|
||||
dpdk_send_pkts(struct mtcp_thread_context *ctxt, int ifidx)
|
||||
{
|
||||
struct dpdk_private_context *dpc;
|
||||
mtcp_manager_t mtcp;
|
||||
int ret, i;
|
||||
|
||||
int ret, i, portid = CONFIG.eths[ifidx].ifindex;
|
||||
|
||||
dpc = (struct dpdk_private_context *)ctxt->io_private_context;
|
||||
mtcp = ctxt->mtcp_manager;
|
||||
ret = 0;
|
||||
|
||||
|
||||
/* if there are packets in the queue... flush them out to the wire */
|
||||
if (dpc->wmbufs[nif].len >/*= MAX_PKT_BURST*/ 0) {
|
||||
if (dpc->wmbufs[ifidx].len >/*= MAX_PKT_BURST*/ 0) {
|
||||
struct rte_mbuf **pkts;
|
||||
#ifdef ENABLE_STATS_IOCTL
|
||||
struct stats_struct ss;
|
||||
#endif /* !ENABLE_STATS_IOCTL */
|
||||
int cnt = dpc->wmbufs[nif].len;
|
||||
pkts = dpc->wmbufs[nif].m_table;
|
||||
int cnt = dpc->wmbufs[ifidx].len;
|
||||
pkts = dpc->wmbufs[ifidx].m_table;
|
||||
#ifdef NETSTAT
|
||||
mtcp->nstat.tx_packets[nif] += cnt;
|
||||
mtcp->nstat.tx_packets[ifidx] += cnt;
|
||||
#ifdef ENABLE_STATS_IOCTL
|
||||
if (likely(dpc->fd >= 0)) {
|
||||
ss.tx_pkts = mtcp->nstat.tx_packets[nif];
|
||||
ss.tx_bytes = mtcp->nstat.tx_bytes[nif];
|
||||
ss.rx_pkts = mtcp->nstat.rx_packets[nif];
|
||||
ss.rx_bytes = mtcp->nstat.rx_bytes[nif];
|
||||
ss.tx_pkts = mtcp->nstat.tx_packets[ifidx];
|
||||
ss.tx_bytes = mtcp->nstat.tx_bytes[ifidx];
|
||||
ss.rx_pkts = mtcp->nstat.rx_packets[ifidx];
|
||||
ss.rx_bytes = mtcp->nstat.rx_bytes[ifidx];
|
||||
ss.qid = ctxt->cpu;
|
||||
ss.dev = nif;
|
||||
ss.dev = portid;
|
||||
ioctl(dpc->fd, 0, &ss);
|
||||
}
|
||||
#endif /* !ENABLE_STATS_IOCTL */
|
||||
#endif
|
||||
do {
|
||||
/* tx cnt # of packets */
|
||||
ret = rte_eth_tx_burst(nif, ctxt->cpu,
|
||||
ret = rte_eth_tx_burst(portid, ctxt->cpu,
|
||||
pkts, cnt);
|
||||
pkts += ret;
|
||||
cnt -= ret;
|
||||
|
@ -272,24 +321,24 @@ dpdk_send_pkts(struct mtcp_thread_context *ctxt, int nif)
|
|||
} while (cnt > 0);
|
||||
|
||||
/* time to allocate fresh mbufs for the queue */
|
||||
for (i = 0; i < dpc->wmbufs[nif].len; i++) {
|
||||
dpc->wmbufs[nif].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]);
|
||||
for (i = 0; i < dpc->wmbufs[ifidx].len; i++) {
|
||||
dpc->wmbufs[ifidx].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]);
|
||||
/* error checking */
|
||||
if (unlikely(dpc->wmbufs[nif].m_table[i] == NULL)) {
|
||||
if (unlikely(dpc->wmbufs[ifidx].m_table[i] == NULL)) {
|
||||
TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n",
|
||||
ctxt->cpu, i, nif);
|
||||
ctxt->cpu, i, ifidx);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
/* reset the len of mbufs var after flushing of packets */
|
||||
dpc->wmbufs[nif].len = 0;
|
||||
dpc->wmbufs[ifidx].len = 0;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint8_t *
|
||||
dpdk_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize)
|
||||
dpdk_get_wptr(struct mtcp_thread_context *ctxt, int ifidx, uint16_t pktsize)
|
||||
{
|
||||
struct dpdk_private_context *dpc;
|
||||
mtcp_manager_t mtcp;
|
||||
|
@ -299,14 +348,14 @@ dpdk_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize)
|
|||
|
||||
dpc = (struct dpdk_private_context *) ctxt->io_private_context;
|
||||
mtcp = ctxt->mtcp_manager;
|
||||
|
||||
|
||||
/* sanity check */
|
||||
if (unlikely(dpc->wmbufs[nif].len == MAX_PKT_BURST))
|
||||
if (unlikely(dpc->wmbufs[ifidx].len == MAX_PKT_BURST))
|
||||
return NULL;
|
||||
|
||||
len_of_mbuf = dpc->wmbufs[nif].len;
|
||||
m = dpc->wmbufs[nif].m_table[len_of_mbuf];
|
||||
|
||||
len_of_mbuf = dpc->wmbufs[ifidx].len;
|
||||
m = dpc->wmbufs[ifidx].m_table[len_of_mbuf];
|
||||
|
||||
/* retrieve the right write offset */
|
||||
ptr = (void *)rte_pktmbuf_mtod(m, struct ether_hdr *);
|
||||
m->pkt_len = m->data_len = pktsize;
|
||||
|
@ -314,12 +363,12 @@ dpdk_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize)
|
|||
m->next = NULL;
|
||||
|
||||
#ifdef NETSTAT
|
||||
mtcp->nstat.tx_bytes[nif] += pktsize + 24;
|
||||
mtcp->nstat.tx_bytes[ifidx] += pktsize + ETHER_OVR;
|
||||
#endif
|
||||
|
||||
|
||||
/* increment the len_of_mbuf var */
|
||||
dpc->wmbufs[nif].len = len_of_mbuf + 1;
|
||||
|
||||
dpc->wmbufs[ifidx].len = len_of_mbuf + 1;
|
||||
|
||||
return (uint8_t *)ptr;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -348,9 +397,10 @@ dpdk_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
|
|||
dpc->rmbufs[ifidx].len = 0;
|
||||
}
|
||||
|
||||
ret = rte_eth_rx_burst((uint8_t)ifidx, ctxt->cpu,
|
||||
int portid = CONFIG.eths[ifidx].ifindex;
|
||||
ret = rte_eth_rx_burst((uint8_t)portid, ctxt->cpu,
|
||||
dpc->pkts_burst, MAX_PKT_BURST);
|
||||
#ifdef RX_IDLE_ENABLE
|
||||
#ifdef RX_IDLE_ENABLE
|
||||
dpc->rx_idle = (likely(ret != 0)) ? 0 : dpc->rx_idle + 1;
|
||||
#endif
|
||||
dpc->rmbufs[ifidx].len = ret;
|
||||
|
@ -358,6 +408,49 @@ dpdk_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
|
|||
return ret;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#ifdef IP_DEFRAG
|
||||
struct rte_mbuf *
|
||||
ip_reassemble(struct dpdk_private_context *dpc, struct rte_mbuf *m)
|
||||
{
|
||||
struct ether_hdr *eth_hdr;
|
||||
struct rte_ip_frag_tbl *tbl;
|
||||
struct rte_ip_frag_death_row *dr;
|
||||
|
||||
/* if packet is IPv4 */
|
||||
if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
|
||||
struct ipv4_hdr *ip_hdr;
|
||||
|
||||
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
|
||||
ip_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
|
||||
|
||||
/* if it is a fragmented packet, then try to reassemble. */
|
||||
if (rte_ipv4_frag_pkt_is_fragmented(ip_hdr)) {
|
||||
struct rte_mbuf *mo;
|
||||
|
||||
tbl = dpc->frag_tbl;
|
||||
dr = &dpc->death_row;
|
||||
|
||||
/* prepare mbuf: setup l2_len/l3_len. */
|
||||
m->l2_len = sizeof(*eth_hdr);
|
||||
m->l3_len = sizeof(*ip_hdr);
|
||||
|
||||
/* process this fragment. */
|
||||
mo = rte_ipv4_frag_reassemble_packet(tbl, dr, m, rte_rdtsc(), ip_hdr);
|
||||
if (mo == NULL)
|
||||
/* no packet to send out. */
|
||||
return NULL;
|
||||
|
||||
/* we have our packet reassembled. */
|
||||
if (mo != m)
|
||||
m = mo;
|
||||
}
|
||||
}
|
||||
|
||||
/* if packet isn't IPv4, just accept it! */
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint8_t *
|
||||
dpdk_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len)
|
||||
{
|
||||
|
@ -365,10 +458,12 @@ dpdk_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *
|
|||
struct rte_mbuf *m;
|
||||
uint8_t *pktbuf;
|
||||
|
||||
dpc = (struct dpdk_private_context *) ctxt->io_private_context;
|
||||
dpc = (struct dpdk_private_context *) ctxt->io_private_context;
|
||||
|
||||
m = dpc->pkts_burst[index];
|
||||
//rte_prefetch0(rte_pktmbuf_mtod(m, void *));
|
||||
#ifdef IP_DEFRAG
|
||||
m = ip_reassemble(dpc, m);
|
||||
#endif
|
||||
*len = m->pkt_len;
|
||||
pktbuf = rte_pktmbuf_mtod(m, uint8_t *);
|
||||
|
||||
|
@ -394,7 +489,7 @@ dpdk_select(struct mtcp_thread_context *ctxt)
|
|||
{
|
||||
#ifdef RX_IDLE_ENABLE
|
||||
struct dpdk_private_context *dpc;
|
||||
|
||||
|
||||
dpc = (struct dpdk_private_context *) ctxt->io_private_context;
|
||||
if (dpc->rx_idle > RX_IDLE_THRESH) {
|
||||
dpc->rx_idle = 0;
|
||||
|
@ -410,7 +505,7 @@ dpdk_destroy_handle(struct mtcp_thread_context *ctxt)
|
|||
struct dpdk_private_context *dpc;
|
||||
int i;
|
||||
|
||||
dpc = (struct dpdk_private_context *) ctxt->io_private_context;
|
||||
dpc = (struct dpdk_private_context *) ctxt->io_private_context;
|
||||
|
||||
/* free wmbufs */
|
||||
for (i = 0; i < num_devices_attached; i++)
|
||||
|
@ -489,10 +584,12 @@ dpdk_load_module(void)
|
|||
struct rte_eth_fc_conf fc_conf;
|
||||
/* setting the rss key */
|
||||
static const uint8_t key[] = {
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 10 */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 20 */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 30 */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 40 */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 50 */
|
||||
0x05, 0x05 /* 60 - 8 */
|
||||
};
|
||||
|
||||
port_conf.rx_adv_conf.rss_conf.rss_key = (uint8_t *)&key;
|
||||
|
@ -500,23 +597,47 @@ dpdk_load_module(void)
|
|||
|
||||
if (!CONFIG.multi_process || (CONFIG.multi_process && CONFIG.multi_process_is_master)) {
|
||||
for (rxlcore_id = 0; rxlcore_id < CONFIG.num_cores; rxlcore_id++) {
|
||||
char name[20];
|
||||
char name[RTE_MEMPOOL_NAMESIZE];
|
||||
uint32_t nb_mbuf;
|
||||
sprintf(name, "mbuf_pool-%d", rxlcore_id);
|
||||
nb_mbuf = NB_MBUF;
|
||||
#ifdef IP_DEFRAG
|
||||
int max_flows;
|
||||
max_flows = CONFIG.max_concurrency / CONFIG.num_cores;
|
||||
|
||||
/*
|
||||
* At any given moment up to <max_flows * (MAX_FRAG_NUM)>
|
||||
* mbufs could be stored int the fragment table.
|
||||
* Plus, each TX queue can hold up to <max_flows> packets.
|
||||
*/
|
||||
|
||||
nb_mbuf = RTE_MAX(max_flows, 2UL * MAX_PKT_BURST) * MAX_FRAG_NUM;
|
||||
nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE;
|
||||
nb_mbuf += RTE_TEST_RX_DESC_DEFAULT + RTE_TEST_TX_DESC_DEFAULT;
|
||||
|
||||
nb_mbuf = RTE_MAX(nb_mbuf, (uint32_t)NB_MBUF);
|
||||
#endif
|
||||
/* create the mbuf pools */
|
||||
pktmbuf_pool[rxlcore_id] =
|
||||
rte_mempool_create(name, NB_MBUF,
|
||||
MBUF_SIZE, MEMPOOL_CACHE_SIZE,
|
||||
sizeof(struct rte_pktmbuf_pool_private),
|
||||
rte_pktmbuf_pool_init, NULL,
|
||||
rte_pktmbuf_init, NULL,
|
||||
rte_socket_id(), 0);
|
||||
rte_mempool_create(name, nb_mbuf,
|
||||
MBUF_SIZE, MEMPOOL_CACHE_SIZE,
|
||||
sizeof(struct rte_pktmbuf_pool_private),
|
||||
rte_pktmbuf_pool_init, NULL,
|
||||
rte_pktmbuf_init, NULL,
|
||||
rte_socket_id(), MEMPOOL_F_SP_PUT |
|
||||
MEMPOOL_F_SC_GET);
|
||||
|
||||
if (pktmbuf_pool[rxlcore_id] == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool, errno: %d\n",
|
||||
rte_errno);
|
||||
rte_errno);
|
||||
}
|
||||
|
||||
|
||||
/* Initialise each port */
|
||||
for (portid = 0; portid < num_devices_attached; portid++) {
|
||||
int i;
|
||||
for (i = 0; i < num_devices_attached; ++i) {
|
||||
/* get portid form the index of attached devices */
|
||||
portid = devices_attached[i];
|
||||
|
||||
/* init port */
|
||||
printf("Initializing port %u... ", (unsigned) portid);
|
||||
fflush(stdout);
|
||||
|
@ -524,7 +645,7 @@ dpdk_load_module(void)
|
|||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
|
||||
ret, (unsigned) portid);
|
||||
|
||||
|
||||
/* init one RX queue per CPU */
|
||||
fflush(stdout);
|
||||
#ifdef DEBUG
|
||||
|
@ -538,44 +659,44 @@ dpdk_load_module(void)
|
|||
rte_eth_dev_socket_id(portid), &rx_conf,
|
||||
pktmbuf_pool[rxlcore_id]);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"rte_eth_rx_queue_setup:err=%d, port=%u, queueid: %d\n",
|
||||
ret, (unsigned) portid, rxlcore_id);
|
||||
}
|
||||
|
||||
|
||||
/* init one TX queue on each port per CPU (this is redundant for this app) */
|
||||
fflush(stdout);
|
||||
for (rxlcore_id = 0; rxlcore_id < CONFIG.num_cores; rxlcore_id++) {
|
||||
ret = rte_eth_tx_queue_setup(portid, rxlcore_id, nb_txd,
|
||||
rte_eth_dev_socket_id(portid), &tx_conf);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"rte_eth_tx_queue_setup:err=%d, port=%u, queueid: %d\n",
|
||||
ret, (unsigned) portid, rxlcore_id);
|
||||
}
|
||||
|
||||
|
||||
/* Start device */
|
||||
ret = rte_eth_dev_start(portid);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
|
||||
ret, (unsigned) portid);
|
||||
|
||||
|
||||
printf("done: \n");
|
||||
rte_eth_promiscuous_enable(portid);
|
||||
|
||||
|
||||
/* retrieve current flow control settings per port */
|
||||
memset(&fc_conf, 0, sizeof(fc_conf));
|
||||
ret = rte_eth_dev_flow_ctrl_get(portid, &fc_conf);
|
||||
if (ret != 0)
|
||||
rte_exit(EXIT_FAILURE, "Failed to get flow control info!\n");
|
||||
|
||||
|
||||
/* and just disable the rx/tx flow control */
|
||||
fc_conf.mode = RTE_FC_NONE;
|
||||
ret = rte_eth_dev_flow_ctrl_set(portid, &fc_conf);
|
||||
if (ret != 0)
|
||||
if (ret != 0)
|
||||
rte_exit(EXIT_FAILURE, "Failed to set flow control info!: errno: %d\n",
|
||||
ret);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
|
||||
(unsigned) portid,
|
||||
|
@ -587,6 +708,8 @@ dpdk_load_module(void)
|
|||
ports_eth_addr[portid].addr_bytes[5]);
|
||||
#endif
|
||||
}
|
||||
/* only check for link status if the thread is master */
|
||||
check_all_ports_link_status(num_devices_attached, 0xFFFFFFFF);
|
||||
} else { /* CONFIG.multi_process && !CONFIG.multi_process_is_master */
|
||||
for (rxlcore_id = 0; rxlcore_id < CONFIG.num_cores; rxlcore_id++) {
|
||||
char name[20];
|
||||
|
@ -598,8 +721,6 @@ dpdk_load_module(void)
|
|||
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
|
||||
}
|
||||
}
|
||||
|
||||
check_all_ports_link_status(num_devices_attached, 0xFFFFFFFF);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int32_t
|
||||
|
@ -610,19 +731,28 @@ dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
|
|||
int len_of_mbuf;
|
||||
struct iphdr *iph;
|
||||
struct tcphdr *tcph;
|
||||
void **argpptr = (void **)argp;
|
||||
#ifdef ENABLELRO
|
||||
uint8_t *payload, *to;
|
||||
int seg_off;
|
||||
#endif
|
||||
|
||||
if (cmd == DRV_NAME) {
|
||||
*argpptr = (void *)dev_info[nif].driver_name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eidx = CONFIG.nif_to_eidx[nif];
|
||||
|
||||
iph = (struct iphdr *)argp;
|
||||
dpc = (struct dpdk_private_context *)ctx->io_private_context;
|
||||
len_of_mbuf = dpc->wmbufs[nif].len;
|
||||
|
||||
len_of_mbuf = dpc->wmbufs[eidx].len;
|
||||
|
||||
switch (cmd) {
|
||||
case PKT_TX_IP_CSUM:
|
||||
if ((dev_info[nif].tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0)
|
||||
goto dev_ioctl_err;
|
||||
m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
|
||||
m = dpc->wmbufs[eidx].m_table[len_of_mbuf - 1];
|
||||
m->ol_flags = PKT_TX_IP_CKSUM | PKT_TX_IPV4;
|
||||
m->l2_len = sizeof(struct ether_hdr);
|
||||
m->l3_len = (iph->ihl<<2);
|
||||
|
@ -630,7 +760,7 @@ dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
|
|||
case PKT_TX_TCP_CSUM:
|
||||
if ((dev_info[nif].tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0)
|
||||
goto dev_ioctl_err;
|
||||
m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
|
||||
m = dpc->wmbufs[eidx].m_table[len_of_mbuf - 1];
|
||||
tcph = (struct tcphdr *)((unsigned char *)iph + (iph->ihl<<2));
|
||||
m->ol_flags |= PKT_TX_TCP_CKSUM;
|
||||
tcph->check = rte_ipv4_phdr_cksum((struct ipv4_hdr *)iph, m->ol_flags);
|
||||
|
@ -667,7 +797,7 @@ dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
|
|||
goto dev_ioctl_err;
|
||||
if ((dev_info[nif].tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0)
|
||||
goto dev_ioctl_err;
|
||||
m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
|
||||
m = dpc->wmbufs[eidx].m_table[len_of_mbuf - 1];
|
||||
iph = rte_pktmbuf_mtod_offset(m, struct iphdr *, sizeof(struct ether_hdr));
|
||||
tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
|
||||
m->l2_len = sizeof(struct ether_hdr);
|
||||
|
@ -678,7 +808,7 @@ dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
|
|||
break;
|
||||
case PKT_RX_IP_CSUM:
|
||||
if ((dev_info[nif].rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) == 0)
|
||||
goto dev_ioctl_err;
|
||||
goto dev_ioctl_err;
|
||||
break;
|
||||
case PKT_RX_TCP_CSUM:
|
||||
if ((dev_info[nif].rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) == 0)
|
||||
|
@ -688,7 +818,7 @@ dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
|
|||
if ((dev_info[nif].tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0)
|
||||
goto dev_ioctl_err;
|
||||
if ((dev_info[nif].tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0)
|
||||
goto dev_ioctl_err;
|
||||
goto dev_ioctl_err;
|
||||
break;
|
||||
default:
|
||||
goto dev_ioctl_err;
|
||||
|
|
|
@ -38,7 +38,7 @@ EthernetOutput(struct mtcp_manager *mtcp, uint16_t h_proto,
|
|||
{
|
||||
uint8_t *buf;
|
||||
struct ethhdr *ethh;
|
||||
int i;
|
||||
int i, eidx;
|
||||
|
||||
/*
|
||||
* -sanity check-
|
||||
|
@ -49,7 +49,13 @@ EthernetOutput(struct mtcp_manager *mtcp, uint16_t h_proto,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
buf = mtcp->iom->get_wptr(mtcp->ctx, nif, iplen + ETHERNET_HEADER_LEN);
|
||||
eidx = CONFIG.nif_to_eidx[nif];
|
||||
if (eidx < 0) {
|
||||
TRACE_INFO("No interface selected!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = mtcp->iom->get_wptr(mtcp->ctx, eidx, iplen + ETHERNET_HEADER_LEN);
|
||||
if (!buf) {
|
||||
//TRACE_DBG("Failed to get available write buffer\n");
|
||||
return NULL;
|
||||
|
@ -65,7 +71,7 @@ EthernetOutput(struct mtcp_manager *mtcp, uint16_t h_proto,
|
|||
|
||||
ethh = (struct ethhdr *)buf;
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
ethh->h_source[i] = CONFIG.eths[nif].haddr[i];
|
||||
ethh->h_source[i] = CONFIG.eths[eidx].haddr[i];
|
||||
ethh->h_dest[i] = dst_haddr[i];
|
||||
}
|
||||
ethh->h_proto = htons(h_proto);
|
||||
|
|
|
@ -111,19 +111,26 @@ mtcp_epoll_create(mctx_t mctx, int size)
|
|||
|
||||
/* create event queues */
|
||||
ep->usr_queue = CreateEventQueue(size);
|
||||
if (!ep->usr_queue)
|
||||
if (!ep->usr_queue) {
|
||||
FreeSocket(mctx, epsocket->id, FALSE);
|
||||
free(ep);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ep->usr_shadow_queue = CreateEventQueue(size);
|
||||
if (!ep->usr_shadow_queue) {
|
||||
DestroyEventQueue(ep->usr_queue);
|
||||
FreeSocket(mctx, epsocket->id, FALSE);
|
||||
free(ep);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ep->mtcp_queue = CreateEventQueue(size);
|
||||
if (!ep->mtcp_queue) {
|
||||
DestroyEventQueue(ep->usr_queue);
|
||||
DestroyEventQueue(ep->usr_shadow_queue);
|
||||
DestroyEventQueue(ep->usr_queue);
|
||||
FreeSocket(mctx, epsocket->id, FALSE);
|
||||
free(ep);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -133,9 +140,19 @@ mtcp_epoll_create(mctx_t mctx, int size)
|
|||
epsocket->ep = ep;
|
||||
|
||||
if (pthread_mutex_init(&ep->epoll_lock, NULL)) {
|
||||
DestroyEventQueue(ep->mtcp_queue);
|
||||
DestroyEventQueue(ep->usr_shadow_queue);
|
||||
DestroyEventQueue(ep->usr_queue);
|
||||
FreeSocket(mctx, epsocket->id, FALSE);
|
||||
free(ep);
|
||||
return -1;
|
||||
}
|
||||
if (pthread_cond_init(&ep->epoll_cond, NULL)) {
|
||||
DestroyEventQueue(ep->mtcp_queue);
|
||||
DestroyEventQueue(ep->usr_shadow_queue);
|
||||
DestroyEventQueue(ep->usr_queue);
|
||||
FreeSocket(mctx, epsocket->id, FALSE);
|
||||
free(ep);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -162,7 +179,6 @@ CloseEpollSocket(mctx_t mctx, int epid)
|
|||
DestroyEventQueue(ep->usr_queue);
|
||||
DestroyEventQueue(ep->usr_shadow_queue);
|
||||
DestroyEventQueue(ep->mtcp_queue);
|
||||
free(ep);
|
||||
|
||||
pthread_mutex_lock(&ep->epoll_lock);
|
||||
mtcp->ep = NULL;
|
||||
|
@ -172,6 +188,7 @@ CloseEpollSocket(mctx_t mctx, int epid)
|
|||
|
||||
pthread_cond_destroy(&ep->epoll_cond);
|
||||
pthread_mutex_destroy(&ep->epoll_lock);
|
||||
free(ep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@ FetchAddress(addr_pool_t ap, int core, int num_queues,
|
|||
const struct sockaddr_in *daddr, struct sockaddr_in *saddr);
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
FetchAddressPerCore(addr_pool_t ap, int core, int num_queues,
|
||||
const struct sockaddr_in *daddr, struct sockaddr_in *saddr);
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
FreeAddress(addr_pool_t ap, const struct sockaddr_in *addr);
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
#include <stdint.h>
|
||||
/* for ps lib funcs */
|
||||
#include "ps.h"
|
||||
/* for onvm */
|
||||
#include "onvm_nflib.h"
|
||||
#include "onvm_pkt_helper.h"
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Declaration to soothe down the warnings
|
||||
|
@ -15,27 +12,27 @@
|
|||
struct mtcp_thread_context;
|
||||
/**
|
||||
* io_module_funcs - contains template for the various 10Gbps pkt I/O
|
||||
* - libraries that can be adopted.
|
||||
* - libraries that can be adopted.
|
||||
*
|
||||
* load_module() : Used to set system-wide I/O module
|
||||
* initialization.
|
||||
*
|
||||
* init_handle() : Used to initialize the driver library
|
||||
* : Also use the context to create/initialize
|
||||
* : a private packet I/O data structures.
|
||||
* init_handle() : Used to initialize the driver library
|
||||
* : Also use the context to create/initialize
|
||||
* : a private packet I/O data structures.
|
||||
*
|
||||
* link_devices() : Used to add link(s) to the mtcp stack.
|
||||
* link_devices() : Used to add link(s) to the mtcp stack.
|
||||
* Returns 0 on success; -1 on failure.
|
||||
*
|
||||
* release_pkt() : release the packet if mTCP does not need
|
||||
* to process it (e.g. non-IPv4, non-TCP pkts).
|
||||
*
|
||||
* get_wptr() : retrieve the next empty pkt buffer for the
|
||||
* application for packet writing. Returns
|
||||
* application for packet writing. Returns
|
||||
* ptr to pkt buffer.
|
||||
*
|
||||
* send_pkts() : transmit batch of packets via interface
|
||||
* idx (=nif).
|
||||
* idx (=nif).
|
||||
* Returns 0 on success; -1 on failure
|
||||
*
|
||||
* get_rptr() : retrieve next pkt for application for
|
||||
|
@ -50,17 +47,17 @@ struct mtcp_thread_context;
|
|||
* select() : for blocking I/O
|
||||
*
|
||||
* destroy_handle() : free up resources allocated during
|
||||
* init_handle(). Normally called during
|
||||
* init_handle(). Normally called during
|
||||
* process termination.
|
||||
*
|
||||
* dev_ioctl() : contains submodules for select drivers
|
||||
* dev_ioctl() : contains submodules for select drivers
|
||||
*
|
||||
*/
|
||||
typedef struct io_module_func {
|
||||
void (*load_module)(void);
|
||||
void (*init_handle)(struct mtcp_thread_context *ctx);
|
||||
void (*init_handle)(struct mtcp_thread_context *ctx);
|
||||
int32_t (*link_devices)(struct mtcp_thread_context *ctx);
|
||||
void (*release_pkt)(struct mtcp_thread_context *ctx, int ifidx, unsigned char *pkt_data, int len);
|
||||
void (*release_pkt)(struct mtcp_thread_context *ctx, int ifidx, unsigned char *pkt_data, int len);
|
||||
uint8_t * (*get_wptr)(struct mtcp_thread_context *ctx, int ifidx, uint16_t len);
|
||||
int32_t (*send_pkts)(struct mtcp_thread_context *ctx, int nif);
|
||||
uint8_t * (*get_rptr)(struct mtcp_thread_context *ctx, int ifidx, int index, uint16_t *len);
|
||||
|
@ -72,22 +69,26 @@ typedef struct io_module_func {
|
|||
/*----------------------------------------------------------------------------*/
|
||||
/* set I/O module context */
|
||||
int SetInterfaceInfo(char *);
|
||||
|
||||
/* retrive device-specific endian type */
|
||||
int FetchEndianType();
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* ptr to the `running' I/O module context */
|
||||
extern io_module_func *current_iomodule_func;
|
||||
|
||||
/* dev_ioctl related macros */
|
||||
#define PKT_TX_IP_CSUM 0x01
|
||||
#define PKT_TX_TCP_CSUM 0x02
|
||||
#define PKT_TX_IP_CSUM 0x01
|
||||
#define PKT_TX_TCP_CSUM 0x02
|
||||
#define PKT_RX_TCP_LROSEG 0x03
|
||||
#define PKT_TX_TCPIP_CSUM 0x04
|
||||
#define PKT_RX_IP_CSUM 0x05
|
||||
#define PKT_RX_TCP_CSUM 0x06
|
||||
#define PKT_TX_TCPIP_CSUM_PEEK 0x07
|
||||
#define DRV_NAME 0x08
|
||||
|
||||
/* registered psio context */
|
||||
#ifdef DISABLE_PSIO
|
||||
#define ps_list_devices(x) 0
|
||||
#define ps_list_devices(x) 0
|
||||
#endif
|
||||
extern io_module_func ps_module_func;
|
||||
struct ps_device devices[MAX_DEVICES];
|
||||
|
@ -109,8 +110,8 @@ extern io_module_func onvm_module_func;
|
|||
current_iomodule_func = &dpdk_module_func; \
|
||||
else if (!strcmp(m, "netmap")) \
|
||||
current_iomodule_func = &netmap_module_func; \
|
||||
else if (!strcmp(m, "onvm")) \
|
||||
current_iomodule_func = &onvm_module_func; \
|
||||
else if (!strcmp(m, "onvm")) \
|
||||
current_iomodule_func = &onvm_module_func; \
|
||||
else \
|
||||
assert(0); \
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#define ERROR (-1)
|
||||
#endif
|
||||
|
||||
#define MAX_CPUS 16
|
||||
|
||||
#define ETHERNET_HEADER_LEN 14 // sizeof(struct ethhdr)
|
||||
#define IP_HEADER_LEN 20 // sizeof(struct iphdr)
|
||||
#define TCP_HEADER_LEN 20 // sizeof(struct tcphdr)
|
||||
|
@ -55,6 +53,9 @@
|
|||
/* blocking api became obsolete */
|
||||
#define BLOCKING_SUPPORT FALSE
|
||||
|
||||
#ifndef MAX_CPUS
|
||||
#define MAX_CPUS 16
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Statistics */
|
||||
#ifdef NETSTAT
|
||||
|
@ -83,6 +84,14 @@
|
|||
#define SBUF_LOCK(lock) pthread_mutex_lock(lock)
|
||||
#define SBUF_UNLOCK(lock) pthread_mutex_unlock(lock)
|
||||
#endif /* USE_SPIN_LOCK */
|
||||
|
||||
/* add macro if it is not defined in /usr/include/sys/queue.h */
|
||||
#ifndef TAILQ_FOREACH_SAFE
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
struct eth_table
|
||||
{
|
||||
|
@ -126,6 +135,7 @@ struct mtcp_config
|
|||
|
||||
/* network interface config */
|
||||
struct eth_table *eths;
|
||||
int *nif_to_eidx; // mapping physic port indexes to that of the configured port-list
|
||||
int eths_num;
|
||||
|
||||
/* route config */
|
||||
|
@ -139,14 +149,6 @@ struct mtcp_config
|
|||
int num_mem_ch;
|
||||
int max_concurrency;
|
||||
|
||||
/* dpdk args */
|
||||
char * core_list;
|
||||
|
||||
/* onvm args */
|
||||
uint16_t service_id;
|
||||
uint16_t instance_id;
|
||||
uint16_t dest_id;
|
||||
|
||||
int max_num_buffers;
|
||||
int rcvbuf_size;
|
||||
int sndbuf_size;
|
||||
|
@ -158,6 +160,13 @@ struct mtcp_config
|
|||
uint8_t multi_process;
|
||||
uint8_t multi_process_is_master;
|
||||
uint8_t multi_process_curr_core;
|
||||
|
||||
#ifdef ENABLE_ONVM
|
||||
/* onvm specific args */
|
||||
uint16_t onvm_serv;
|
||||
uint16_t onvm_inst;
|
||||
uint16_t onvm_dest;
|
||||
#endif
|
||||
};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
struct mtcp_context
|
||||
|
|
|
@ -36,8 +36,6 @@ struct mtcp_conf
|
|||
int rcvbuf_size;
|
||||
int sndbuf_size;
|
||||
|
||||
char * core_list;
|
||||
|
||||
int tcp_timewait;
|
||||
int tcp_timeout;
|
||||
};
|
||||
|
@ -45,7 +43,7 @@ struct mtcp_conf
|
|||
typedef struct mtcp_context *mctx_t;
|
||||
|
||||
int
|
||||
mtcp_init(const char *config_file, int argc, char *argv[]);
|
||||
mtcp_init(const char *config_file);
|
||||
|
||||
void
|
||||
mtcp_destroy();
|
||||
|
@ -56,9 +54,6 @@ mtcp_getconf(struct mtcp_conf *conf);
|
|||
int
|
||||
mtcp_setconf(const struct mtcp_conf *conf);
|
||||
|
||||
int
|
||||
mtcp_parse_args(int argc, char *argv[]);
|
||||
|
||||
int
|
||||
mtcp_core_affinitize(int cpu);
|
||||
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
/* for getifaddrs */
|
||||
#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
#ifdef ENABLE_ONVM
|
||||
/* for onvm */
|
||||
#include "onvm_nflib.h"
|
||||
#include "onvm_pkt_helper.h"
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
io_module_func *current_iomodule_func = &dpdk_module_func;
|
||||
#define ALL_STRING "all"
|
||||
|
@ -38,13 +43,13 @@ io_module_func *current_iomodule_func = &dpdk_module_func;
|
|||
/* onvm struct for port info lookup */
|
||||
extern struct port_info *ports;
|
||||
|
||||
static int
|
||||
static int
|
||||
GetNumQueues()
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[MAX_PROCLINE_LEN];
|
||||
int queue_cnt;
|
||||
|
||||
|
||||
fp = fopen("/proc/interrupts", "r");
|
||||
if (!fp) {
|
||||
TRACE_CONFIG("Failed to read data from /proc/interrupts!\n");
|
||||
|
@ -68,7 +73,7 @@ GetNumQueues()
|
|||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
SetInterfaceInfo(char* dev_name_list)
|
||||
SetInterfaceInfo(char* dev_name_list)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int eidx = 0;
|
||||
|
@ -77,11 +82,13 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
int set_all_inf = (strncmp(dev_name_list, ALL_STRING, sizeof(ALL_STRING))==0);
|
||||
|
||||
TRACE_CONFIG("Loading interface setting\n");
|
||||
|
||||
|
||||
CONFIG.eths = (struct eth_table *)
|
||||
calloc(MAX_DEVICES, sizeof(struct eth_table));
|
||||
if (!CONFIG.eths)
|
||||
if (!CONFIG.eths) {
|
||||
TRACE_ERROR("Can't allocate space for CONFIG.eths\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (current_iomodule_func == &ps_module_func) {
|
||||
/* calculate num_devices now! */
|
||||
|
@ -89,47 +96,48 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
if (num_devices == -1) {
|
||||
perror("ps_list_devices");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Create socket */
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sock == -1) {
|
||||
perror("socket");
|
||||
TRACE_ERROR("socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
/* To Do: Parse dev_name_list rather than use strstr */
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
strcpy(ifr.ifr_name, devices[i].name);
|
||||
|
||||
|
||||
/* getting interface information */
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
|
||||
|
||||
|
||||
if (!set_all_inf && strstr(dev_name_list, ifr.ifr_name) == NULL)
|
||||
continue;
|
||||
|
||||
|
||||
/* Setting informations */
|
||||
eidx = CONFIG.eths_num++;
|
||||
strcpy(CONFIG.eths[eidx].dev_name, ifr.ifr_name);
|
||||
CONFIG.eths[eidx].ifindex = devices[i].ifindex;
|
||||
|
||||
|
||||
/* getting address */
|
||||
if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) {
|
||||
struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
||||
CONFIG.eths[eidx].ip_addr = *(uint32_t *)&sin;
|
||||
}
|
||||
|
||||
|
||||
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0 ) {
|
||||
for (j = 0; j < ETH_ALEN; j ++) {
|
||||
CONFIG.eths[eidx].haddr[j] = ifr.ifr_addr.sa_data[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Net MASK */
|
||||
if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) {
|
||||
struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
||||
CONFIG.eths[eidx].netmask = *(uint32_t *)&sin;
|
||||
}
|
||||
|
||||
|
||||
/* add to attached devices */
|
||||
for (j = 0; j < num_devices_attached; j++) {
|
||||
if (devices_attached[j] == devices[i].ifindex) {
|
||||
|
@ -138,20 +146,23 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
}
|
||||
devices_attached[num_devices_attached] = devices[i].ifindex;
|
||||
num_devices_attached++;
|
||||
|
||||
} else {
|
||||
|
||||
} else {
|
||||
perror("SIOCGIFFLAGS");
|
||||
}
|
||||
}
|
||||
num_queues = GetNumQueues();
|
||||
if (num_queues <= 0) {
|
||||
TRACE_CONFIG("Failed to find NIC queues!\n");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
if (num_queues > num_cpus) {
|
||||
TRACE_CONFIG("Too many NIC queues available.\n");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
close(sock);
|
||||
} else if (current_iomodule_func == &dpdk_module_func) {
|
||||
#ifndef DISABLE_DPDK
|
||||
int cpu = CONFIG.num_cores;
|
||||
|
@ -160,7 +171,7 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
char mem_channels[5];
|
||||
int ret;
|
||||
static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
|
||||
|
||||
|
||||
/* get the cpu mask */
|
||||
for (ret = 0; ret < cpu; ret++)
|
||||
cpumask = (cpumask | (1 << ret));
|
||||
|
@ -175,17 +186,17 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
sprintf(mem_channels, "%d", CONFIG.num_mem_ch);
|
||||
|
||||
/* initialize the rte env first, what a waste of implementation effort! */
|
||||
char *argv[] = {"",
|
||||
"-c",
|
||||
cpumaskbuf,
|
||||
"-n",
|
||||
char *argv[] = {"",
|
||||
"-c",
|
||||
cpumaskbuf,
|
||||
"-n",
|
||||
mem_channels,
|
||||
"--proc-type=auto",
|
||||
""
|
||||
};
|
||||
const int argc = 6;
|
||||
|
||||
/*
|
||||
/*
|
||||
* re-set getopt extern variable optind.
|
||||
* this issue was a bitch to debug
|
||||
* rte_eal_init() internally uses getopt() syscall
|
||||
|
@ -205,11 +216,11 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
if (num_devices == 0) {
|
||||
rte_exit(EXIT_FAILURE, "No Ethernet port!\n");
|
||||
}
|
||||
|
||||
|
||||
/* get mac addr entries of 'detected' dpdk ports */
|
||||
for (ret = 0; ret < num_devices; ret++)
|
||||
rte_eth_macaddr_get(ret, &ports_eth_addr[ret]);
|
||||
|
||||
|
||||
num_queues = MIN(CONFIG.num_cores, MAX_CPUS);
|
||||
|
||||
struct ifaddrs *ifap;
|
||||
|
@ -220,16 +231,16 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
perror("getifaddrs: ");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
iter_if = ifap;
|
||||
do {
|
||||
if (iter_if->ifa_addr->sa_family == AF_INET &&
|
||||
!set_all_inf &&
|
||||
!set_all_inf &&
|
||||
(seek=strstr(dev_name_list, iter_if->ifa_name)) != NULL &&
|
||||
/* check if the interface was not aliased */
|
||||
*(seek + strlen(iter_if->ifa_name)) != ':') {
|
||||
struct ifreq ifr;
|
||||
|
||||
|
||||
/* Setting informations */
|
||||
eidx = CONFIG.eths_num++;
|
||||
strcpy(CONFIG.eths[eidx].dev_name, iter_if->ifa_name);
|
||||
|
@ -239,8 +250,9 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sock == -1) {
|
||||
perror("socket");
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* getting address */
|
||||
if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) {
|
||||
struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
||||
|
@ -259,29 +271,29 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
CONFIG.eths[eidx].netmask = *(uint32_t *)&sin;
|
||||
}
|
||||
close(sock);
|
||||
|
||||
|
||||
for (j = 0; j < num_devices; j++) {
|
||||
if (!memcmp(&CONFIG.eths[eidx].haddr[0], &ports_eth_addr[j],
|
||||
ETH_ALEN))
|
||||
CONFIG.eths[eidx].ifindex = j;
|
||||
}
|
||||
|
||||
|
||||
/* add to attached devices */
|
||||
for (j = 0; j < num_devices_attached; j++) {
|
||||
if (devices_attached[j] == CONFIG.eths[eidx].ifindex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
devices_attached[num_devices_attached] = CONFIG.eths[eidx].ifindex;
|
||||
num_devices_attached++;
|
||||
fprintf(stderr, "Total number of attached devices: %d\n",
|
||||
num_devices_attached);
|
||||
fprintf(stderr, "Interface name: %s\n",
|
||||
fprintf(stderr, "Interface name: %s\n",
|
||||
iter_if->ifa_name);
|
||||
}
|
||||
iter_if = iter_if->ifa_next;
|
||||
} while (iter_if != NULL);
|
||||
|
||||
|
||||
freeifaddrs(ifap);
|
||||
#endif /* !DISABLE_DPDK */
|
||||
} else if (current_iomodule_func == &netmap_module_func) {
|
||||
|
@ -296,39 +308,40 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
perror("getifaddrs: ");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
iter_if = ifap;
|
||||
do {
|
||||
if (iter_if->ifa_addr->sa_family == AF_INET &&
|
||||
!set_all_inf &&
|
||||
!set_all_inf &&
|
||||
(seek=strstr(dev_name_list, iter_if->ifa_name)) != NULL &&
|
||||
/* check if the interface was not aliased */
|
||||
*(seek + strlen(iter_if->ifa_name)) != ':') {
|
||||
struct ifreq ifr;
|
||||
|
||||
|
||||
/* Setting informations */
|
||||
eidx = CONFIG.eths_num++;
|
||||
strcpy(CONFIG.eths[eidx].dev_name, iter_if->ifa_name);
|
||||
strcpy(ifr.ifr_name, iter_if->ifa_name);
|
||||
|
||||
|
||||
/* Create socket */
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sock == -1) {
|
||||
perror("socket");
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* getting address */
|
||||
if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) {
|
||||
struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
||||
CONFIG.eths[eidx].ip_addr = *(uint32_t *)&sin;
|
||||
}
|
||||
|
||||
|
||||
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0 ) {
|
||||
for (j = 0; j < ETH_ALEN; j ++) {
|
||||
CONFIG.eths[eidx].haddr[j] = ifr.ifr_addr.sa_data[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Net MASK */
|
||||
if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) {
|
||||
struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
||||
|
@ -342,32 +355,32 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
CONFIG.eths[eidx].ifindex = ifr.ifr_ifindex;
|
||||
#endif
|
||||
CONFIG.eths[eidx].ifindex = eidx;//if_nametoindex(ifr.ifr_name);
|
||||
TRACE_INFO("Ifindex of interface %s is: %d\n",
|
||||
TRACE_INFO("Ifindex of interface %s is: %d\n",
|
||||
ifr.ifr_name, CONFIG.eths[eidx].ifindex);
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* add to attached devices */
|
||||
for (j = 0; j < num_devices_attached; j++) {
|
||||
if (devices_attached[j] == CONFIG.eths[eidx].ifindex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
devices_attached[num_devices_attached] = if_nametoindex(ifr.ifr_name);//CONFIG.eths[eidx].ifindex;
|
||||
num_devices_attached++;
|
||||
fprintf(stderr, "Total number of attached devices: %d\n",
|
||||
num_devices_attached);
|
||||
fprintf(stderr, "Interface name: %s\n",
|
||||
fprintf(stderr, "Interface name: %s\n",
|
||||
iter_if->ifa_name);
|
||||
}
|
||||
iter_if = iter_if->ifa_next;
|
||||
} while (iter_if != NULL);
|
||||
|
||||
|
||||
freeifaddrs(ifap);
|
||||
#endif /* !DISABLE_NETMAP */
|
||||
} else if (current_iomodule_func == &onvm_module_func) {
|
||||
#ifndef DISABLE_DPDK
|
||||
#ifdef ENABLE_ONVM
|
||||
int cpu = CONFIG.num_cores;
|
||||
uint32_t cpumask = 0;
|
||||
char cpumaskbuf[10];
|
||||
|
@ -388,13 +401,13 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sprintf(mem_channels, "%d", CONFIG.num_mem_ch);
|
||||
sprintf(service, "%d", CONFIG.service_id);
|
||||
sprintf(instance, "%d", CONFIG.instance_id);
|
||||
sprintf(service, "%d", CONFIG.onvm_serv);
|
||||
sprintf(instance, "%d", CONFIG.onvm_inst);
|
||||
|
||||
/* initialize the rte env first, what a waste of implementation effort! */
|
||||
char *argv[] = {"",
|
||||
"-l",
|
||||
CONFIG.core_list,
|
||||
"-c",
|
||||
cpumaskbuf,
|
||||
"-n",
|
||||
mem_channels,
|
||||
"--proc-type=secondary",
|
||||
|
@ -486,7 +499,48 @@ SetInterfaceInfo(char* dev_name_list)
|
|||
} while (iter_if != NULL);
|
||||
|
||||
freeifaddrs(ifap);
|
||||
#endif /* !DISABLE_DPDK */
|
||||
}return 0;
|
||||
#endif /* ENABLE_ONVM */
|
||||
}
|
||||
|
||||
CONFIG.nif_to_eidx = (int*)calloc(MAX_DEVICES, sizeof(int));
|
||||
|
||||
if (!CONFIG.nif_to_eidx) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; ++i) {
|
||||
CONFIG.nif_to_eidx[i] = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < CONFIG.eths_num; ++i) {
|
||||
|
||||
j = CONFIG.eths[i].ifindex;
|
||||
if (j >= MAX_DEVICES) {
|
||||
TRACE_ERROR("ifindex of eths_%d exceed the limit: %d\n", i, j);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* the physic port index of the i-th port listed in the config file is j*/
|
||||
CONFIG.nif_to_eidx[j] = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
FetchEndianType()
|
||||
{
|
||||
#ifndef DISABLE_DPDK
|
||||
char *argv;
|
||||
char **argp = &argv;
|
||||
/* dpdk_module_func logic down below */
|
||||
dpdk_module_func.dev_ioctl(NULL, CONFIG.eths[0].ifindex, DRV_NAME, (void *)argp);
|
||||
if (!strcmp(*argp, "net_i40e"))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -9,7 +9,6 @@ inline int
|
|||
GetOutputInterface(uint32_t daddr)
|
||||
{
|
||||
int nif = -1;
|
||||
int nif_index = -1;
|
||||
int i;
|
||||
int prefix = 0;
|
||||
|
||||
|
@ -30,22 +29,7 @@ GetOutputInterface(uint32_t daddr)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
/* match nif to eth nif_index */
|
||||
for (i = 0; i < CONFIG.eths_num; i++) {
|
||||
if (CONFIG.eths[i].ifindex == nif) {
|
||||
nif_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nif_index < 0) {
|
||||
uint8_t *da = (uint8_t *)&daddr;
|
||||
TRACE_ERROR("[WARNING] No eth id for route to %u.%u.%u.%u\n",
|
||||
da[0], da[1], da[2], da[3]);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return nif_index;
|
||||
return nif;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint8_t *
|
||||
|
@ -92,8 +76,16 @@ IPOutputStandalone(struct mtcp_manager *mtcp, uint8_t protocol,
|
|||
iph->check = 0;
|
||||
|
||||
#ifndef DISABLE_HWCSUM
|
||||
if (mtcp->iom->dev_ioctl != NULL)
|
||||
rc = mtcp->iom->dev_ioctl(mtcp->ctx, nif, PKT_TX_TCPIP_CSUM_PEEK, iph);
|
||||
if (mtcp->iom->dev_ioctl != NULL) {
|
||||
switch(iph->protocol) {
|
||||
case IPPROTO_TCP:
|
||||
rc = mtcp->iom->dev_ioctl(mtcp->ctx, nif, PKT_TX_TCPIP_CSUM_PEEK, iph);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
rc = mtcp->iom->dev_ioctl(mtcp->ctx, nif, PKT_TX_IP_CSUM, iph);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* otherwise calculate IP checksum in S/W */
|
||||
if (rc == -1)
|
||||
iph->check = ip_fast_csum(iph, iph->ihl);
|
||||
|
@ -154,8 +146,16 @@ IPOutput(struct mtcp_manager *mtcp, tcp_stream *stream, uint16_t tcplen)
|
|||
|
||||
#ifndef DISABLE_HWCSUM
|
||||
/* offload IP checkum if possible */
|
||||
if (mtcp->iom->dev_ioctl != NULL)
|
||||
rc = mtcp->iom->dev_ioctl(mtcp->ctx, nif, PKT_TX_TCPIP_CSUM_PEEK, iph);
|
||||
if (mtcp->iom->dev_ioctl != NULL) {
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP:
|
||||
rc = mtcp->iom->dev_ioctl(mtcp->ctx, nif, PKT_TX_TCPIP_CSUM_PEEK, iph);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
rc = mtcp->iom->dev_ioctl(mtcp->ctx, nif, PKT_TX_IP_CSUM, iph);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* otherwise calculate IP checksum in S/W */
|
||||
if (rc == -1)
|
||||
iph->check = ip_fast_csum(iph, iph->ihl);
|
||||
|
|
|
@ -67,7 +67,7 @@ MPCreate(int chunk_size, size_t total_size, int is_hugepage)
|
|||
if (!mp->mp_startptr) {
|
||||
TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size);
|
||||
assert(0);
|
||||
if (mp) free(mp);
|
||||
free(mp);
|
||||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
|
@ -76,7 +76,7 @@ MPCreate(int chunk_size, size_t total_size, int is_hugepage)
|
|||
if (res != 0) {
|
||||
TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size);
|
||||
assert(0);
|
||||
if (mp) free(mp);
|
||||
free(mp);
|
||||
return (NULL);
|
||||
}
|
||||
#ifdef HUGETABLE
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* for io_module_func def'ns */
|
||||
#include "io_module.h"
|
||||
#ifndef DISABLE_DPDK
|
||||
#ifdef ENABLE_ONVM
|
||||
/* for mtcp related def'ns */
|
||||
#include "mtcp.h"
|
||||
/* for errno */
|
||||
|
@ -216,13 +216,13 @@ onvm_send_pkts(struct mtcp_thread_context *ctxt, int nif)
|
|||
|
||||
for(i=0;i<cnt;i++){
|
||||
meta = onvm_get_pkt_meta(pkts[i]);
|
||||
if (CONFIG.dest_id == (uint16_t) -1){
|
||||
if (CONFIG.onvm_dest == (uint16_t) -1){
|
||||
meta->action = ONVM_NF_ACTION_OUT;
|
||||
meta->destination = CONFIG.eths[nif].ifindex;
|
||||
}
|
||||
else {
|
||||
meta->action = ONVM_NF_ACTION_TONF;
|
||||
meta->destination = CONFIG.dest_id;
|
||||
meta->destination = CONFIG.onvm_dest;
|
||||
}
|
||||
}
|
||||
ret = rte_ring_enqueue_bulk(tx_ring, (void * const*)pkts ,cnt);
|
||||
|
@ -529,4 +529,4 @@ io_module_func onvm_module_func = {
|
|||
.dev_ioctl = NULL
|
||||
};
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#endif /* !DISABLE_DPDK */
|
||||
#endif /* ENABLE_ONVM */
|
||||
|
|
|
@ -88,8 +88,8 @@ mtcp_pipe(mctx_t mctx, int pipeid[2])
|
|||
FreeSocket(mctx, socket[0]->id, FALSE);
|
||||
FreeSocket(mctx, socket[1]->id, FALSE);
|
||||
free(pp->buf);
|
||||
free(pp);
|
||||
pthread_mutex_destroy(&pp->pipe_lock);
|
||||
free(pp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1243,8 +1243,14 @@ ProcessTCPPacket(mtcp_manager_t mtcp,
|
|||
/* SYN retransmit implies our SYN/ACK was lost. Resend */
|
||||
if (tcph->syn && seq == cur_stream->rcvvar->irs)
|
||||
Handle_TCP_ST_LISTEN(mtcp, cur_ts, cur_stream, tcph);
|
||||
else
|
||||
else {
|
||||
Handle_TCP_ST_SYN_RCVD(mtcp, cur_ts, cur_stream, tcph, ack_seq);
|
||||
if (payloadlen > 0 && cur_stream->state == TCP_ST_ESTABLISHED) {
|
||||
Handle_TCP_ST_ESTABLISHED(mtcp, cur_ts, cur_stream, tcph,
|
||||
seq, ack_seq, payload,
|
||||
payloadlen, window);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_ST_ESTABLISHED:
|
||||
|
|
|
@ -365,6 +365,7 @@ FlushTCPSendingBuffer(mtcp_manager_t mtcp, tcp_stream *cur_stream, uint32_t cur_
|
|||
int16_t sndlen;
|
||||
uint32_t window;
|
||||
int packets = 0;
|
||||
uint8_t wack_sent = 0;
|
||||
|
||||
if (!sndvar->sndbuf) {
|
||||
TRACE_ERROR("Stream %d: No send buffer available.\n", cur_stream->id);
|
||||
|
@ -410,6 +411,9 @@ FlushTCPSendingBuffer(mtcp_manager_t mtcp, tcp_stream *cur_stream, uint32_t cur_
|
|||
len = buffered_len;
|
||||
}
|
||||
|
||||
if (len > window)
|
||||
len = window;
|
||||
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
|
@ -426,9 +430,11 @@ FlushTCPSendingBuffer(mtcp_manager_t mtcp, tcp_stream *cur_stream, uint32_t cur_
|
|||
"peer_wnd: %u, (snd_nxt-snd_una): %u\n",
|
||||
sndvar->peer_wnd, seq - sndvar->snd_una);
|
||||
#endif
|
||||
if (TS_TO_MSEC(cur_ts - sndvar->ts_lastack_sent) > 500) {
|
||||
if (!wack_sent && TS_TO_MSEC(cur_ts - sndvar->ts_lastack_sent) > 500) {
|
||||
EnqueueACK(mtcp, cur_stream, cur_ts, ACK_OPT_WACK);
|
||||
}
|
||||
else
|
||||
wack_sent = 1;
|
||||
}
|
||||
packets = -3;
|
||||
goto out;
|
||||
|
@ -441,6 +447,8 @@ FlushTCPSendingBuffer(mtcp_manager_t mtcp, tcp_stream *cur_stream, uint32_t cur_
|
|||
goto out;
|
||||
}
|
||||
packets++;
|
||||
|
||||
window -= len;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -790,14 +798,15 @@ GetSender(mtcp_manager_t mtcp, tcp_stream *cur_stream)
|
|||
{
|
||||
if (cur_stream->sndvar->nif_out < 0) {
|
||||
return mtcp->g_sender;
|
||||
}
|
||||
|
||||
} else if (cur_stream->sndvar->nif_out >= CONFIG.eths_num) {
|
||||
int eidx = CONFIG.nif_to_eidx[cur_stream->sndvar->nif_out];
|
||||
if (eidx < 0 || eidx >= CONFIG.eths_num) {
|
||||
TRACE_ERROR("(NEVER HAPPEN) Failed to find appropriate sender.\n");
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
return mtcp->n_sender[cur_stream->sndvar->nif_out];
|
||||
}
|
||||
|
||||
return mtcp->n_sender[eidx];
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
inline void
|
||||
|
|
|
@ -197,6 +197,7 @@ RBInit(rb_manager_t rbm, uint32_t init_seq)
|
|||
buff->data = MPAllocateChunk(rbm->mp);
|
||||
if(!buff->data){
|
||||
perror("rb_init MPAllocateChunk");
|
||||
free(buff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ SBManagerCreate(size_t chunk_size, uint32_t cnum)
|
|||
sbm->freeq = CreateSBQueue(cnum);
|
||||
if (!sbm->freeq) {
|
||||
TRACE_ERROR("Failed to create free buffer queue.\n");
|
||||
MPDestroy(sbm->mp);
|
||||
free(sbm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -62,12 +64,13 @@ SBInit(sb_manager_t sbm, uint32_t init_seq)
|
|||
if (!buf) {
|
||||
buf = (struct tcp_send_buffer *)malloc(sizeof(struct tcp_send_buffer));
|
||||
if (!buf) {
|
||||
perror("calloc() for buf");
|
||||
perror("malloc() for buf");
|
||||
return NULL;
|
||||
}
|
||||
buf->data = MPAllocateChunk(sbm->mp);
|
||||
if (!buf->data) {
|
||||
TRACE_ERROR("Failed to fetch memory chunk for data.\n");
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
sbm->cur_num++;
|
||||
|
|
|
@ -500,9 +500,14 @@ DestroyTCPStream(mtcp_manager_t mtcp, tcp_stream *stream)
|
|||
if (mtcp->ap) {
|
||||
ret = FreeAddress(mtcp->ap, &addr);
|
||||
} else {
|
||||
int nif;
|
||||
nif = GetOutputInterface(addr.sin_addr.s_addr);
|
||||
ret = FreeAddress(ap[nif], &addr);
|
||||
int nif = GetOutputInterface(addr.sin_addr.s_addr);
|
||||
if (nif < 0) {
|
||||
TRACE_ERROR("nif is negative!\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
int eidx = CONFIG.nif_to_eidx[nif];
|
||||
ret = FreeAddress(ap[eidx], &addr);
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
TRACE_ERROR("(NEVER HAPPEN) Failed to free address.\n");
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
### GCC ###
|
||||
GCC=@CC@
|
||||
GCC_OPT = -m64 -Wall -fPIC -c
|
||||
|
||||
ifeq ($(shell uname -m),x86_64)
|
||||
GCC_OPT = -m64
|
||||
else
|
||||
GCC_OPT =
|
||||
endif
|
||||
GCC_OPT += -Wall -fPIC -c
|
||||
GCC_OPT += -DNDEBUG -O3 -DNETSTAT -DINFO -DDBGERR -DDBGCERR
|
||||
|
||||
|
||||
|
@ -8,7 +14,7 @@ GCC_OPT += -DNDEBUG -O3 -DNETSTAT -DINFO -DDBGERR -DDBGCERR
|
|||
CFLAGS = -I./include/
|
||||
|
||||
### SOURCE CODE ###
|
||||
SRCS = tdate_parse.c http_parsing.c
|
||||
SRCS = tdate_parse.c http_parsing.c netlib.c
|
||||
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
|
|
|
@ -106,12 +106,10 @@ http_header_str_val(const char* buf, const char *key, const int keylen,
|
|||
}
|
||||
|
||||
/* copy value data */
|
||||
if (temp) {
|
||||
while (*temp && !CR_OR_NEWLINE(*temp) && i < value_len-1)
|
||||
value[i++] = *temp++;
|
||||
value[i] = 0;
|
||||
}
|
||||
|
||||
while (*temp && !CR_OR_NEWLINE(*temp) && i < value_len-1)
|
||||
value[i++] = *temp++;
|
||||
value[i] = 0;
|
||||
|
||||
if (i == 0) {
|
||||
*value = 0;
|
||||
return NULL;
|
||||
|
|
|
@ -31,6 +31,7 @@ int GetNumCPUCores(void);
|
|||
int AffinitizeThreadToCore(int core);
|
||||
int CreateServerSocket(int port, int isNonBlocking);
|
||||
int CreateConnectionSocket(in_addr_t addr, int port, int isNonBlocking);
|
||||
int mystrtol(const char *nptr, int base);
|
||||
|
||||
/* processing options */
|
||||
struct Options {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "netlib.h"
|
||||
|
||||
|
@ -233,3 +234,27 @@ GetHeaderLong(const char* buf, const char* header, int hdrsize, long int *val)
|
|||
}
|
||||
return (FALSE);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
mystrtol(const char *nptr, int base)
|
||||
{
|
||||
int rval;
|
||||
char *endptr;
|
||||
|
||||
errno = 0;
|
||||
rval = strtol(nptr, &endptr, 10);
|
||||
/* check for strtol errors */
|
||||
if ((errno == ERANGE && (rval == LONG_MAX ||
|
||||
rval == LONG_MIN))
|
||||
|| (errno != 0 && rval == 0)) {
|
||||
perror("strtol");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (endptr == nptr) {
|
||||
fprintf(stderr, "Parsing strtol error!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue